From f84b6a31dcb097d68c5d5330648ce1181442dcbe Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Wed, 15 Mar 2023 17:59:30 -0700 Subject: [PATCH] Remove Sticker Creator in favor of Web App --- .eslintignore | 2 - .eslintrc.js | 2 - .github/workflows/benchmark.yml | 2 +- .github/workflows/ci.yml | 2 +- .gitignore | 5 - .prettierignore | 2 - .storybook/main.js | 5 +- .storybook/preview.tsx | 9 +- ACKNOWLEDGMENTS.md | 60 ---- CONTRIBUTING.md | 1 - _locales/en/messages.json | 102 +++--- app/main.ts | 85 +---- app/menu.ts | 4 +- package.json | 23 +- scripts/esbuild.js | 2 +- sticker-creator/_mixins.scss | 12 - sticker-creator/app/index.scss | 19 - sticker-creator/app/index.tsx | 60 ---- sticker-creator/app/stages/AppStage.scss | 50 --- sticker-creator/app/stages/AppStage.tsx | 105 ------ sticker-creator/app/stages/DropStage.scss | 27 -- sticker-creator/app/stages/DropStage.tsx | 43 --- sticker-creator/app/stages/EmojiStage.tsx | 29 -- sticker-creator/app/stages/MetaStage.scss | 75 ---- sticker-creator/app/stages/MetaStage.tsx | 102 ------ sticker-creator/app/stages/ShareStage.scss | 27 -- sticker-creator/app/stages/ShareStage.tsx | 97 ----- sticker-creator/app/stages/UploadStage.scss | 13 - sticker-creator/app/stages/UploadStage.tsx | 84 ----- sticker-creator/components/ConfirmModal.scss | 14 - sticker-creator/components/ConfirmModal.tsx | 44 --- sticker-creator/components/ShareButtons.scss | 30 -- .../components/ShareButtons.stories.tsx | 26 -- sticker-creator/components/ShareButtons.tsx | 77 ---- sticker-creator/components/StickerFrame.scss | 143 -------- .../components/StickerFrame.stories.tsx | 78 ---- sticker-creator/components/StickerFrame.tsx | 304 ---------------- sticker-creator/components/StickerGrid.scss | 16 - sticker-creator/components/StickerGrid.tsx | 140 -------- .../components/StickerPackPreview.scss | 129 ------- .../components/StickerPackPreview.stories.tsx | 29 -- .../components/StickerPackPreview.tsx | 39 -- .../components/Toaster.stories.tsx | 39 -- sticker-creator/components/Toaster.tsx | 47 --- sticker-creator/custom.d.ts | 4 - sticker-creator/elements/Button.scss | 83 ----- sticker-creator/elements/Button.stories.tsx | 61 ---- sticker-creator/elements/Button.tsx | 44 --- sticker-creator/elements/ConfirmDialog.scss | 101 ------ .../elements/ConfirmDialog.stories.tsx | 39 -- sticker-creator/elements/ConfirmDialog.tsx | 46 --- sticker-creator/elements/CopyText.scss | 39 -- sticker-creator/elements/CopyText.stories.tsx | 27 -- sticker-creator/elements/CopyText.tsx | 41 --- sticker-creator/elements/DropZone.scss | 64 ---- sticker-creator/elements/DropZone.stories.tsx | 19 - sticker-creator/elements/DropZone.tsx | 70 ---- sticker-creator/elements/LabeledCheckbox.scss | 60 ---- .../elements/LabeledCheckbox.stories.tsx | 25 -- sticker-creator/elements/LabeledCheckbox.tsx | 46 --- sticker-creator/elements/LabeledInput.scss | 58 --- .../elements/LabeledInput.stories.tsx | 30 -- sticker-creator/elements/LabeledInput.tsx | 42 --- sticker-creator/elements/MessageBubble.scss | 16 - .../elements/MessageBubble.stories.tsx | 27 -- sticker-creator/elements/MessageBubble.tsx | 20 -- sticker-creator/elements/MessageMeta.scss | 36 -- sticker-creator/elements/MessageMeta.tsx | 59 ---- sticker-creator/elements/MessageSticker.scss | 13 - .../elements/MessageSticker.stories.tsx | 27 -- sticker-creator/elements/MessageSticker.tsx | 24 -- sticker-creator/elements/PageHeader.scss | 25 -- .../elements/PageHeader.stories.tsx | 26 -- sticker-creator/elements/PageHeader.tsx | 16 - sticker-creator/elements/ProgressBar.scss | 27 -- .../elements/ProgressBar.stories.tsx | 27 -- sticker-creator/elements/ProgressBar.tsx | 27 -- sticker-creator/elements/StickerPreview.scss | 103 ------ .../elements/StickerPreview.stories.tsx | 26 -- sticker-creator/elements/StickerPreview.tsx | 78 ---- sticker-creator/elements/StoryRow.scss | 31 -- sticker-creator/elements/StoryRow.tsx | 39 -- sticker-creator/elements/Toast.scss | 18 - sticker-creator/elements/Toast.stories.tsx | 23 -- sticker-creator/elements/Toast.tsx | 26 -- sticker-creator/elements/Typography.scss | 78 ---- .../elements/Typography.stories.tsx | 40 --- sticker-creator/elements/Typography.tsx | 76 ---- sticker-creator/elements/icons/AddEmoji.tsx | 12 - sticker-creator/elements/icons/index.tsx | 4 - sticker-creator/index.html | 18 - sticker-creator/index.tsx | 12 - sticker-creator/preload.ts | 11 - sticker-creator/root.tsx | 33 -- sticker-creator/store/ducks/stickers.ts | 332 ------------------ sticker-creator/store/index.ts | 11 - sticker-creator/store/reducer.ts | 12 - sticker-creator/util/history.ts | 6 - sticker-creator/util/i18n.tsx | 116 ------ sticker-creator/util/preload.ts | 35 -- sticker-creator/util/useStickerDropzone.ts | 20 -- sticker-creator/window/phase1-dependencies.ts | 21 -- sticker-creator/window/phase2-signal.ts | 20 -- .../window/phase3-sticker-functions.ts | 289 --------------- sticker-creator/window/phase4-theme.ts | 25 -- ts/background.ts | 1 - ts/components/TitleBarContainer.tsx | 7 +- ts/state/ducks/user.ts | 1 - ts/test-node/app/menu_test.ts | 8 +- .../util/getAnimatedPngDataIfExists_test.ts | 60 ---- ts/types/menu.ts | 2 - ts/util/getAnimatedPngDataIfExists.ts | 85 ----- ts/util/lint/exceptions.json | 14 - ts/util/lint/linter.ts | 4 - tsconfig.json | 8 +- webpack.config.ts | 99 ------ yarn.lock | 59 +--- 117 files changed, 67 insertions(+), 5269 deletions(-) delete mode 100644 sticker-creator/_mixins.scss delete mode 100644 sticker-creator/app/index.scss delete mode 100644 sticker-creator/app/index.tsx delete mode 100644 sticker-creator/app/stages/AppStage.scss delete mode 100644 sticker-creator/app/stages/AppStage.tsx delete mode 100644 sticker-creator/app/stages/DropStage.scss delete mode 100644 sticker-creator/app/stages/DropStage.tsx delete mode 100644 sticker-creator/app/stages/EmojiStage.tsx delete mode 100644 sticker-creator/app/stages/MetaStage.scss delete mode 100644 sticker-creator/app/stages/MetaStage.tsx delete mode 100644 sticker-creator/app/stages/ShareStage.scss delete mode 100644 sticker-creator/app/stages/ShareStage.tsx delete mode 100644 sticker-creator/app/stages/UploadStage.scss delete mode 100644 sticker-creator/app/stages/UploadStage.tsx delete mode 100644 sticker-creator/components/ConfirmModal.scss delete mode 100644 sticker-creator/components/ConfirmModal.tsx delete mode 100644 sticker-creator/components/ShareButtons.scss delete mode 100644 sticker-creator/components/ShareButtons.stories.tsx delete mode 100644 sticker-creator/components/ShareButtons.tsx delete mode 100644 sticker-creator/components/StickerFrame.scss delete mode 100644 sticker-creator/components/StickerFrame.stories.tsx delete mode 100644 sticker-creator/components/StickerFrame.tsx delete mode 100644 sticker-creator/components/StickerGrid.scss delete mode 100644 sticker-creator/components/StickerGrid.tsx delete mode 100644 sticker-creator/components/StickerPackPreview.scss delete mode 100644 sticker-creator/components/StickerPackPreview.stories.tsx delete mode 100644 sticker-creator/components/StickerPackPreview.tsx delete mode 100644 sticker-creator/components/Toaster.stories.tsx delete mode 100644 sticker-creator/components/Toaster.tsx delete mode 100644 sticker-creator/custom.d.ts delete mode 100644 sticker-creator/elements/Button.scss delete mode 100644 sticker-creator/elements/Button.stories.tsx delete mode 100644 sticker-creator/elements/Button.tsx delete mode 100644 sticker-creator/elements/ConfirmDialog.scss delete mode 100644 sticker-creator/elements/ConfirmDialog.stories.tsx delete mode 100644 sticker-creator/elements/ConfirmDialog.tsx delete mode 100644 sticker-creator/elements/CopyText.scss delete mode 100644 sticker-creator/elements/CopyText.stories.tsx delete mode 100644 sticker-creator/elements/CopyText.tsx delete mode 100644 sticker-creator/elements/DropZone.scss delete mode 100644 sticker-creator/elements/DropZone.stories.tsx delete mode 100644 sticker-creator/elements/DropZone.tsx delete mode 100644 sticker-creator/elements/LabeledCheckbox.scss delete mode 100644 sticker-creator/elements/LabeledCheckbox.stories.tsx delete mode 100644 sticker-creator/elements/LabeledCheckbox.tsx delete mode 100644 sticker-creator/elements/LabeledInput.scss delete mode 100644 sticker-creator/elements/LabeledInput.stories.tsx delete mode 100644 sticker-creator/elements/LabeledInput.tsx delete mode 100644 sticker-creator/elements/MessageBubble.scss delete mode 100644 sticker-creator/elements/MessageBubble.stories.tsx delete mode 100644 sticker-creator/elements/MessageBubble.tsx delete mode 100644 sticker-creator/elements/MessageMeta.scss delete mode 100644 sticker-creator/elements/MessageMeta.tsx delete mode 100644 sticker-creator/elements/MessageSticker.scss delete mode 100644 sticker-creator/elements/MessageSticker.stories.tsx delete mode 100644 sticker-creator/elements/MessageSticker.tsx delete mode 100644 sticker-creator/elements/PageHeader.scss delete mode 100644 sticker-creator/elements/PageHeader.stories.tsx delete mode 100644 sticker-creator/elements/PageHeader.tsx delete mode 100644 sticker-creator/elements/ProgressBar.scss delete mode 100644 sticker-creator/elements/ProgressBar.stories.tsx delete mode 100644 sticker-creator/elements/ProgressBar.tsx delete mode 100644 sticker-creator/elements/StickerPreview.scss delete mode 100644 sticker-creator/elements/StickerPreview.stories.tsx delete mode 100644 sticker-creator/elements/StickerPreview.tsx delete mode 100644 sticker-creator/elements/StoryRow.scss delete mode 100644 sticker-creator/elements/StoryRow.tsx delete mode 100644 sticker-creator/elements/Toast.scss delete mode 100644 sticker-creator/elements/Toast.stories.tsx delete mode 100644 sticker-creator/elements/Toast.tsx delete mode 100644 sticker-creator/elements/Typography.scss delete mode 100644 sticker-creator/elements/Typography.stories.tsx delete mode 100644 sticker-creator/elements/Typography.tsx delete mode 100644 sticker-creator/elements/icons/AddEmoji.tsx delete mode 100644 sticker-creator/elements/icons/index.tsx delete mode 100644 sticker-creator/index.html delete mode 100644 sticker-creator/index.tsx delete mode 100644 sticker-creator/preload.ts delete mode 100644 sticker-creator/root.tsx delete mode 100644 sticker-creator/store/ducks/stickers.ts delete mode 100644 sticker-creator/store/index.ts delete mode 100644 sticker-creator/store/reducer.ts delete mode 100644 sticker-creator/util/history.ts delete mode 100644 sticker-creator/util/i18n.tsx delete mode 100644 sticker-creator/util/preload.ts delete mode 100644 sticker-creator/util/useStickerDropzone.ts delete mode 100644 sticker-creator/window/phase1-dependencies.ts delete mode 100644 sticker-creator/window/phase2-signal.ts delete mode 100644 sticker-creator/window/phase3-sticker-functions.ts delete mode 100644 sticker-creator/window/phase4-theme.ts delete mode 100644 ts/test-node/util/getAnimatedPngDataIfExists_test.ts delete mode 100644 ts/util/getAnimatedPngDataIfExists.ts delete mode 100644 webpack.config.ts diff --git a/.eslintignore b/.eslintignore index 1ec3c5e12a98..e32aec680db5 100644 --- a/.eslintignore +++ b/.eslintignore @@ -13,7 +13,6 @@ js/util_worker.js libtextsecure/components.js libtextsecure/test/test.js test/test.js -sticker-creator/dist/** ts/protobuf/compiled.d.ts # Third-party files @@ -23,7 +22,6 @@ js/WebAudioRecorderMp3.js # TypeScript generated files app/**/*.js ts/**/*.js -sticker-creator/**/*.js .eslintrc.js webpack.config.ts diff --git a/.eslintrc.js b/.eslintrc.js index fac01b8d3cc7..b9da930820be 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -241,8 +241,6 @@ module.exports = { 'ts/**/*.ts', 'ts/**/*.tsx', 'app/**/*.ts', - 'sticker-creator/**/*.ts', - 'sticker-creator/**/*.tsx', 'build/intl-linter/**/*.ts', ], parser: '@typescript-eslint/parser', diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index a264dee5511a..5302dadcf61f 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -51,7 +51,7 @@ jobs: - name: Build typescript run: yarn generate - name: Bundle - run: yarn build:webpack + run: yarn build:esbuild:prod - name: Run startup benchmarks run: | diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 004763d3ce91..3dd9ea534c5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -208,7 +208,7 @@ jobs: - name: Build typescript run: yarn generate - name: Bundle - run: yarn build:webpack + run: yarn build:esbuild:prod - name: Run mock server tests run: | diff --git a/.gitignore b/.gitignore index 1a0e01389ffe..2676ec88825c 100644 --- a/.gitignore +++ b/.gitignore @@ -34,15 +34,10 @@ ts/sql/mainWorker.bundle.js.LICENSE.txt app/*.js ts/**/*.js ts/protobuf/*.d.ts -sticker-creator/**/*.js # CSS Modules **/*.scss.d.ts -# Sticker Creator -sticker-creator/dist/* -sticker-creator/**/*.js - # Editors /.idea /.vscode diff --git a/.prettierignore b/.prettierignore index d404a3229150..641883b41ea9 100644 --- a/.prettierignore +++ b/.prettierignore @@ -3,7 +3,6 @@ # Generated files app/**/*.js -sticker-creator/**/*.js config/local-*.json config/local.json dist/** @@ -19,7 +18,6 @@ ts/protobuf/*.d.ts ts/protobuf/*.js stylesheets/manifest.css ts/util/lint/exceptions.json -sticker-creator/dist/** # Third-party files node_modules/** diff --git a/.storybook/main.js b/.storybook/main.js index 7620cd52be0c..3310856f670a 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -5,10 +5,7 @@ module.exports = { typescript: { reactDocgen: false, }, - stories: [ - '../ts/components/**/*.stories.tsx', - '../sticker-creator/**/*.stories.tsx', - ], + stories: ['../ts/components/**/*.stories.tsx'], addons: [ '@storybook/addon-a11y', '@storybook/addon-actions', diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx index d59faf9faadb..cd0316b0e993 100644 --- a/.storybook/preview.tsx +++ b/.storybook/preview.tsx @@ -8,7 +8,6 @@ import { withKnobs, boolean, optionsKnob } from '@storybook/addon-knobs'; import * as styles from './styles.scss'; import messages from '../_locales/en/messages.json'; import { ClassyProvider } from '../ts/components/PopperRootContext'; -import { I18n } from '../sticker-creator/util/i18n'; import { StorybookThemeContext } from './StorybookThemeContext'; import { ThemeType } from '../ts/types/Util'; import { setupI18n } from '../ts/util/setupI18n'; @@ -72,13 +71,7 @@ const withModeAndThemeProvider = (Story, context) => { ); }; -const withI18n = (Story, context) => ( - - - -); - -export const decorators = [withModeAndThemeProvider, withI18n]; +export const decorators = [withModeAndThemeProvider]; export const parameters = { axe: { diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md index d7e3918914c3..1395fdbd66a0 100644 --- a/ACKNOWLEDGMENTS.md +++ b/ACKNOWLEDGMENTS.md @@ -131,18 +131,6 @@ Signal Desktop makes use of the following open source projects. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE -## array-move - - MIT License - - Copyright (c) Sindre Sorhus (sindresorhus.com) - - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ## backbone Copyright (c) 2010-2019 Jeremy Ashkenas, DocumentCloud @@ -2017,30 +2005,6 @@ Signal Desktop makes use of the following open source projects. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -## react-dropzone - - The MIT License (MIT) - - Copyright (c) 2018 Param Aggarwal - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - ## react-hot-loader MIT License @@ -2169,30 +2133,6 @@ Signal Desktop makes use of the following open source projects. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -## react-sortable-hoc - - The MIT License (MIT) - - Copyright (c) 2016, Claudéric Demers - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - ## react-textarea-autosize The MIT License (MIT) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d4eb51d0fc43..91789b11fd4b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -59,7 +59,6 @@ git clone https://github.com/signalapp/Signal-Desktop.git cd Signal-Desktop yarn install --frozen-lockfile # Install and build dependencies (this will take a while) yarn generate # Generate final JS and CSS assets -yarn build:webpack # Build parts of the app that use webpack (Sticker Creator) yarn test # A good idea to make sure tests run first yarn start # Start Signal! ``` diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 3fef9d307aca..5229a3d440ee 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -788,7 +788,7 @@ }, "signalDesktopStickerCreator": { "message": "Sticker pack creator", - "description": "Title of the window that pops up with Signal Desktop preferences in it" + "description": "(deleted 03/15/2023) Title of the window that pops up with Signal Desktop preferences in it" }, "aboutSignalDesktop": { "message": "About Signal Desktop", @@ -2989,203 +2989,203 @@ }, "StickerCreator--title": { "message": "Sticker pack creator", - "description": "The title of the Sticker Pack Creator window" + "description": "(deleted 03/15/2023) The title of the Sticker Pack Creator window" }, "StickerCreator--DropZone--staticText": { "message": "Click to add or drop images here", - "description": "Text which appears on the Sticker Creator drop zone when there is no active drag" + "description": "(deleted 03/15/2023) Text which appears on the Sticker Creator drop zone when there is no active drag" }, "StickerCreator--DropZone--activeText": { "message": "Drop images here", - "description": "Text which appears on the Sticker Creator drop zone when there is an active drag" + "description": "(deleted 03/15/2023) Text which appears on the Sticker Creator drop zone when there is an active drag" }, "StickerCreator--Preview--title": { "message": "Sticker pack", - "description": "The 'title' of the sticker pack preview 'modal'" + "description": "(deleted 03/15/2023) The 'title' of the sticker pack preview 'modal'" }, "StickerCreator--ConfirmDialog--cancel": { "message": "Cancel", - "description": "The default text for the confirm dialog cancel button" + "description": "(deleted 03/15/2023) The default text for the confirm dialog cancel button" }, "StickerCreator--CopyText--button": { "message": "Copy", - "description": "The text which appears on the copy button for the sticker creator share screen" + "description": "(deleted 03/15/2023) The text which appears on the copy button for the sticker creator share screen" }, "StickerCreator--ShareButtons--facebook": { "message": "Facebook", - "description": "Title for Facebook button" + "description": "(deleted 03/15/2023) Title for Facebook button" }, "StickerCreator--ShareButtons--twitter": { "message": "Twitter", - "description": "Title for Twitter button" + "description": "(deleted 03/15/2023) Title for Twitter button" }, "StickerCreator--ShareButtons--pinterest": { "message": "Pinterest", - "description": "Title for Pinterest button" + "description": "(deleted 03/15/2023) Title for Pinterest button" }, "StickerCreator--ShareButtons--whatsapp": { "message": "WhatsApp", - "description": "Title for WhatsApp button" + "description": "(deleted 03/15/2023) Title for WhatsApp button" }, "StickerCreator--AppStage--next": { "message": "Next", - "description": "Default text for the next button on all stages of the sticker creator" + "description": "(deleted 03/15/2023) Default text for the next button on all stages of the sticker creator" }, "StickerCreator--AppStage--prev": { "message": "Back", - "description": "Default text for the previous button on all stages of the sticker creator" + "description": "(deleted 03/15/2023) Default text for the previous button on all stages of the sticker creator" }, "icu:StickerCreator--DropStage--title": { "messageformat": "Add your stickers", - "description": "Title for the drop stage of the sticker creator" + "description": "(deleted 03/15/2023) Title for the drop stage of the sticker creator" }, "StickerCreator--DropStage--removeSticker": { "message": "Remove sticker", - "description": "Label for the X button used to remove a staged sticker" + "description": "(deleted 03/15/2023) Label for the X button used to remove a staged sticker" }, "StickerCreator--DropStage--dragDrop": { "message": "Click or drag/drop a file to add a sticker", - "description": "Shown on the + section of the file addition stage of sticker pack creation" + "description": "(deleted 03/15/2023) Shown on the + section of the file addition stage of sticker pack creation" }, "StickerCreator--DropStage--help": { "message": "Stickers must be in PNG, APNG, or WebP format with a transparent background and 512x512 pixels. Recommended margin is 16px.", - "description": "Help text for the drop stage of the sticker creator" + "description": "(deleted 03/15/2023) Help text for the drop stage of the sticker creator" }, "StickerCreator--DropStage--showMargins": { "message": "Show margins", - "description": "Text for the show margins toggle on the drop stage of the sticker creator" + "description": "(deleted 03/15/2023) Text for the show margins toggle on the drop stage of the sticker creator" }, "icu:StickerCreator--DropStage--addMore": { "messageformat": "Add {count, number} or more", - "description": "Text to show user how many more stickers they must add" + "description": "(deleted 03/15/2023) Text to show user how many more stickers they must add" }, "StickerCreator--EmojiStage--title": { "message": "Add an emoji to each sticker", - "description": "Title for the drop stage of the sticker creator" + "description": "(deleted 03/15/2023) Title for the drop stage of the sticker creator" }, "StickerCreator--EmojiStage--help": { "message": "This allows us to suggest stickers to you as you're messaging.", - "description": "Help text for the drop stage of the sticker creator" + "description": "(deleted 03/15/2023) Help text for the drop stage of the sticker creator" }, "StickerCreator--MetaStage--title": { "message": "Just a few more details...", - "description": "Title for the meta stage of the sticker creator" + "description": "(deleted 03/15/2023) Title for the meta stage of the sticker creator" }, "StickerCreator--MetaStage--Field--title": { "message": "Title", - "description": "Label for the title input of the meta stage of the sticker creator" + "description": "(deleted 03/15/2023) Label for the title input of the meta stage of the sticker creator" }, "StickerCreator--MetaStage--Field--author": { "message": "Author", - "description": "Label for the author input of the meta stage of the sticker creator" + "description": "(deleted 03/15/2023) Label for the author input of the meta stage of the sticker creator" }, "StickerCreator--MetaStage--Field--cover": { "message": "Cover image", - "description": "Label for the cover image picker of the meta stage of the sticker creator" + "description": "(deleted 03/15/2023) Label for the cover image picker of the meta stage of the sticker creator" }, "StickerCreator--MetaStage--Field--cover--help": { "message": "This is the image that will show up when you share your sticker pack", - "description": "Help text for the cover image picker of the meta stage of the sticker creator" + "description": "(deleted 03/15/2023) Help text for the cover image picker of the meta stage of the sticker creator" }, "StickerCreator--MetaStage--ConfirmDialog--title": { "message": "Are you sure you want to upload your sticker pack?", - "description": "Title for the confirm dialog on the meta stage of the sticker creator" + "description": "(deleted 03/15/2023) Title for the confirm dialog on the meta stage of the sticker creator" }, "StickerCreator--MetaStage--ConfirmDialog--confirm": { "message": "Upload", - "description": "Text for the upload button in the confirmation dialog on the meta stage of the sticker creator" + "description": "(deleted 03/15/2023) Text for the upload button in the confirmation dialog on the meta stage of the sticker creator" }, "StickerCreator--MetaStage--ConfirmDialog--text": { "message": "You will no longer be able to make edits or delete after creating a sticker pack.", - "description": "The text inside the confirmation dialog on the meta stage of the sticker creator" + "description": "(deleted 03/15/2023) The text inside the confirmation dialog on the meta stage of the sticker creator" }, "StickerCreator--UploadStage--title": { "message": "Creating your sticker pack", - "description": "Title for the upload stage of the sticker creator" + "description": "(deleted 03/15/2023) Title for the upload stage of the sticker creator" }, "StickerCreator--UploadStage-uploaded": { "message": "$count$ of $total$ uploaded", - "description": "Title for the upload stage of the sticker creator" + "description": "(deleted 03/15/2023) Title for the upload stage of the sticker creator" }, "StickerCreator--ShareStage--title": { "message": "Congratulations! You created a sticker pack.", - "description": "Title for the share stage of the sticker creator" + "description": "(deleted 03/15/2023) Title for the share stage of the sticker creator" }, "StickerCreator--ShareStage--help": { "message": "Access your new stickers through the sticker icon, or share with your friends using the link below.", - "description": "Help text for the share stage of the sticker creator" + "description": "(deleted 03/15/2023) Help text for the share stage of the sticker creator" }, "StickerCreator--ShareStage--callToAction": { "message": "Use the hashtag $hashtag$ to help other people find the URLs for any custom sticker packs that you would like to make publicly accessible.", - "description": "Call to action text for the share stage of the sticker creator" + "description": "(deleted 03/15/2023) Call to action text for the share stage of the sticker creator" }, "StickerCreator--ShareStage--copyTitle": { "message": "Sticker Pack URL", - "description": "Title for the copy button on the share stage of the sticker creator" + "description": "(deleted 03/15/2023) Title for the copy button on the share stage of the sticker creator" }, "StickerCreator--ShareStage--close": { "message": "Close", - "description": "Text for the close button on the share stage of the sticker creator" + "description": "(deleted 03/15/2023) Text for the close button on the share stage of the sticker creator" }, "StickerCreator--ShareStage--createAnother": { "message": "Create another sticker pack", - "description": "Text for the create another sticker pack button on the share stage of the sticker creator" + "description": "(deleted 03/15/2023) Text for the create another sticker pack button on the share stage of the sticker creator" }, "StickerCreator--ShareStage--socialMessage": { "message": "Check out this new sticker pack I created for Signal. #makeprivacystick", - "description": "Text which is shared to social media platforms for sticker packs" + "description": "(deleted 03/15/2023) Text which is shared to social media platforms for sticker packs" }, "icu:StickerCreator--Toasts--imagesAdded": { "messageformat": "{count, plural, one {1 image} other {# images}} added", - "description": "Text for the toast when images are added to the sticker creator" + "description": "(deleted 03/15/2023) Text for the toast when images are added to the sticker creator" }, "StickerCreator--Toasts--animated": { "message": "Animated stickers are not currently supported", - "description": "Text for the toast when an image that is animated was dropped on the sticker creator" + "description": "(deleted 03/15/2023) Text for the toast when an image that is animated was dropped on the sticker creator" }, "StickerCreator--Toasts--tooLarge": { "message": "Dropped image is too large", - "description": "Text for the toast when an image that is too large was dropped on the sticker creator" + "description": "(deleted 03/15/2023) Text for the toast when an image that is too large was dropped on the sticker creator" }, "StickerCreator--Toasts--errorProcessing": { "message": "Error processing image", - "description": "Text for the toast when an image cannot be processed was dropped on the sticker creator with a generic error" + "description": "(deleted 03/15/2023) Text for the toast when an image cannot be processed was dropped on the sticker creator with a generic error" }, "StickerCreator--Toasts--APNG--notSquare": { "message": "Animated PNG stickers must be square", - "description": "Text for the toast when someone tries to upload a non-square APNG" + "description": "(deleted 03/15/2023) Text for the toast when someone tries to upload a non-square APNG" }, "StickerCreator--Toasts--mustLoopForever": { "message": "Animated stickers must loop forever", - "description": "Text for the toast when an image in the sticker creator does not animate forever" + "description": "(deleted 03/15/2023) Text for the toast when an image in the sticker creator does not animate forever" }, "StickerCreator--Toasts--APNG--dimensionsTooLarge": { "message": "Animated PNG sticker dimensions are too large", - "description": "Text for the toast when an APNG image in the sticker creator is too large" + "description": "(deleted 03/15/2023) Text for the toast when an APNG image in the sticker creator is too large" }, "StickerCreator--Toasts--APNG--dimensionsTooSmall": { "message": "Animated PNG sticker dimensions are too small", - "description": "Text for the toast when an APNG image in the sticker creator is too small" + "description": "(deleted 03/15/2023) Text for the toast when an APNG image in the sticker creator is too small" }, "StickerCreator--Toasts--errorUploading": { "message": "Error uploading stickers: $message$", - "description": "Text for the toast when a sticker pack cannot be uploaded" + "description": "(deleted 03/15/2023) Text for the toast when a sticker pack cannot be uploaded" }, "StickerCreator--Toasts--linkedCopied": { "message": "Link copied", - "description": "Text for the toast when a link for sharing is copied from the Sticker Creator" + "description": "(deleted 03/15/2023) Text for the toast when a link for sharing is copied from the Sticker Creator" }, "StickerCreator--StickerPreview--light": { "message": "My sticker in light theme", - "description": "Text for the sticker preview for the light theme" + "description": "(deleted 03/15/2023) Text for the sticker preview for the light theme" }, "StickerCreator--StickerPreview--dark": { "message": "My sticker in dark theme", - "description": "Text for the sticker preview for the dark theme" + "description": "(deleted 03/15/2023) Text for the sticker preview for the dark theme" }, "StickerCreator--Authentication--error": { "message": "Please set up Signal on your phone and desktop to use the Sticker Pack Creator", - "description": "The error message which appears when the user has not linked their account and attempts to use the Sticker Creator" + "description": "(deleted 03/15/2023) The error message which appears when the user has not linked their account and attempts to use the Sticker Creator" }, "icu:ArtCreator--Authentication--error": { "messageformat": "Please set up Signal on your phone and desktop to use the Sticker Pack Creator", diff --git a/app/main.ts b/app/main.ts index fdd964905a74..75bbc1ca759e 100644 --- a/app/main.ts +++ b/app/main.ts @@ -95,7 +95,7 @@ import type { MenuActionType } from '../ts/types/menu'; import { createTemplate } from './menu'; import { installFileHandler, installWebHandler } from './protocol_filter'; import * as OS from '../ts/OS'; -import { isProduction, isStaging } from '../ts/util/version'; +import { isProduction } from '../ts/util/version'; import { isSgnlHref, isCaptchaHref, @@ -1342,85 +1342,6 @@ async function getIsLinked() { } } -let stickerCreatorWindow: BrowserWindow | undefined; -async function showStickerCreator() { - if (!(await getIsLinked())) { - const message = getResolvedMessagesLocale().i18n( - 'StickerCreator--Authentication--error' - ); - - await dialog.showMessageBox({ - type: 'warning', - message, - }); - - return; - } - - if (stickerCreatorWindow) { - stickerCreatorWindow.show(); - return; - } - - const { x = 0, y = 0 } = windowConfig || {}; - - const titleBarOverlay = await getTitleBarOverlay(); - - const options = { - x: x + 100, - y: y + 100, - width: 800, - minWidth: 800, - height: 650, - title: getResolvedMessagesLocale().i18n('signalDesktopStickerCreator'), - titleBarStyle: nonMainTitleBarStyle, - titleBarOverlay, - autoHideMenuBar: true, - backgroundColor: await getBackgroundColor(), - show: false, - webPreferences: { - ...defaultWebPrefs, - nodeIntegration: false, - nodeIntegrationInWorker: false, - sandbox: false, - contextIsolation: false, - preload: join(__dirname, '../sticker-creator/preload.js'), - nativeWindowOpen: true, - spellcheck: await getSpellCheckSetting(), - }, - }; - - stickerCreatorWindow = new BrowserWindow(options); - setupSpellChecker(stickerCreatorWindow, getResolvedMessagesLocale()); - - handleCommonWindowEvents(stickerCreatorWindow, titleBarOverlay); - - const appUrl = process.env.SIGNAL_ENABLE_HTTP - ? prepareUrl( - new URL('http://localhost:6380/sticker-creator/dist/index.html') - ) - : prepareFileUrl([__dirname, '../sticker-creator/dist/index.html']); - - stickerCreatorWindow.on('closed', () => { - stickerCreatorWindow = undefined; - }); - - stickerCreatorWindow.once('ready-to-show', () => { - if (!stickerCreatorWindow) { - return; - } - - stickerCreatorWindow.show(); - - if (config.get('openDevTools')) { - // Open the DevTools. - stickerCreatorWindow.webContents.openDevTools(); - } - }); - - await safeLoadURL(stickerCreatorWindow, await appUrl); -} - async function openArtCreator() { if (!(await getIsLinked())) { const message = getResolvedMessagesLocale().i18n( @@ -2013,7 +1934,6 @@ function setupMenu(options?: Partial) { devTools: defaultWebPrefs.devTools, includeSetup: false, isProduction: isProduction(app.getVersion()), - isStaging: isStaging(app.getVersion()), platform, // actions @@ -2030,7 +1950,6 @@ function setupMenu(options?: Partial) { showDebugLog: showDebugLogWindow, showKeyboardShortcuts, showSettings: showSettingsWindow, - showStickerCreator, showWindow, // overrides @@ -2642,8 +2561,6 @@ ipc.handle('executeMenuAction', async (_event, action: MenuActionType) => { showKeyboardShortcuts(); } else if (action === 'showSettings') { drop(showSettingsWindow()); - } else if (action === 'showStickerCreator') { - drop(showStickerCreator()); } else if (action === 'showWindow') { showWindow(); } else { diff --git a/app/menu.ts b/app/menu.ts index 64c6cea9307a..d68bfe09bf94 100644 --- a/app/menu.ts +++ b/app/menu.ts @@ -22,7 +22,6 @@ export const createTemplate = ( const { isProduction, - isStaging, devTools, includeSetup, openContactUs, @@ -38,7 +37,6 @@ export const createTemplate = ( showDebugLog, showKeyboardShortcuts, showSettings, - showStickerCreator, openArtCreator, } = options; @@ -48,7 +46,7 @@ export const createTemplate = ( submenu: [ { label: i18n('mainMenuCreateStickers'), - click: isStaging ? openArtCreator : showStickerCreator, + click: openArtCreator, }, { label: i18n('mainMenuSettings'), diff --git a/package.json b/package.json index 704414aa2a49..f5aded305cc2 100644 --- a/package.json +++ b/package.json @@ -55,28 +55,22 @@ "svgo": "svgo --multipass images/**/*.svg", "transpile": "run-p check:types build:esbuild", "check:types": "tsc --noEmit", - "clean-transpile-once": "rimraf app/**/*.js app/*.js sticker-creator/**/*.js sticker-creator/*.js ts/**/*.js ts/*.js tsconfig.tsbuildinfo", + "clean-transpile-once": "rimraf app/**/*.js app/*.js ts/**/*.js ts/*.js tsconfig.tsbuildinfo", "clean-transpile": "yarn run clean-transpile-once && yarn run clean-transpile-once", "open-coverage": "open coverage/lcov-report/index.html", "ready": "npm-run-all --print-label clean-transpile generate --parallel lint lint-deps lint-intl test-node test-electron", "dev": "run-p --print-label dev:*", "dev:transpile": "run-p \"check:types --watch\" dev:esbuild", - "dev:webpack": "run-p dev:esbuild dev:webpack:sticker-creator", - "dev:webpack:sticker-creator": "cross-env NODE_ENV=development webpack serve --mode development", "dev:esbuild": "node scripts/esbuild.js --watch", - "dev:typed-scss": "yarn build:typed-scss -w", "dev:storybook": "cross-env SIGNAL_ENV=storybook start-storybook -p 6006 -s ./", "dev:sass": "yarn sass --watch", - "build": "run-s --print-label generate build:typed-scss build:webpack build:release", + "build": "run-s --print-label generate build:esbuild:prod build:release", "build:acknowledgments": "node scripts/generate-acknowledgments.js", - "build:dev": "run-s --print-label generate build:typed-scss build:webpack", - "build:typed-scss": "tsm sticker-creator", - "build:webpack": "run-p build:webpack:sticker-creator \"build:esbuild --prod\"", - "build:webpack:sticker-creator": "cross-env NODE_ENV=production webpack", + "build:dev": "run-s --print-label generate build:esbuild:prod", "build:esbuild": "node scripts/esbuild.js", + "build:esbuild:prod": "node scripts/esbuild.js --prod", "build:electron": "electron-builder --config.extraMetadata.environment=$SIGNAL_ENV", "build:release": "cross-env SIGNAL_ENV=production yarn build:electron -- --config.directories.output=release", - "preverify:ts": "yarn build:typed-scss", "verify": "run-p --print-label verify:*", "verify:ts": "tsc --noEmit", "electron:install-app-deps": "electron-builder install-app-deps" @@ -94,7 +88,6 @@ "@signalapp/libsignal-client": "0.22.0", "@signalapp/ringrtc": "2.25.2", "@types/fabric": "4.5.3", - "array-move": "2.1.0", "backbone": "1.4.0", "blob-util": "2.0.2", "blueimp-load-image": "5.14.0", @@ -151,7 +144,6 @@ "react-blurhash": "0.1.2", "react-contextmenu": "2.11.0", "react-dom": "17.0.2", - "react-dropzone": "10.2.2", "react-hot-loader": "4.13.0", "react-intl": "6.1.1", "react-measure": "2.3.0", @@ -159,7 +151,6 @@ "react-quill": "2.0.0-beta.4", "react-redux": "7.2.8", "react-router-dom": "5.0.1", - "react-sortable-hoc": "2.0.0", "react-textarea-autosize": "8.3.4", "react-virtualized": "9.22.3", "read-last-lines": "1.8.0", @@ -240,7 +231,6 @@ "@types/react-measure": "2.0.5", "@types/react-redux": "7.1.24", "@types/react-router-dom": "4.3.4", - "@types/react-sortable-hoc": "0.6.5", "@types/react-virtualized": "9.18.12", "@types/redux-logger": "3.0.7", "@types/rimraf": "2.0.2", @@ -254,7 +244,6 @@ "@types/yargs": "17.0.7", "@typescript-eslint/eslint-plugin": "5.47.0", "@typescript-eslint/parser": "5.47.0", - "arraybuffer-loader": "1.0.3", "asar": "3.1.0", "axe-core": "4.1.4", "babel-core": "7.0.0-bridge.0", @@ -283,7 +272,6 @@ "eslint-plugin-mocha": "10.1.0", "eslint-plugin-more": "1.0.5", "eslint-plugin-react": "7.31.10", - "file-loader": "4.2.0", "html-webpack-plugin": "5.3.1", "json-to-ast": "2.1.0", "mocha": "9.1.3", @@ -470,9 +458,6 @@ "sounds/*", "build/icons", "node_modules/**", - "sticker-creator/preload.js", - "sticker-creator/window/*.js", - "sticker-creator/dist/**", "!node_modules/underscore/**", "!node_modules/emoji-datasource/emoji_pretty.json", "!node_modules/emoji-datasource/**/*.png", diff --git a/scripts/esbuild.js b/scripts/esbuild.js index 064df944aa6d..f71bae78b869 100644 --- a/scripts/esbuild.js +++ b/scripts/esbuild.js @@ -68,7 +68,7 @@ async function main() { format: 'cjs', mainFields: ['browser', 'main'], entryPoints: glob - .sync('{app,ts,sticker-creator}/**/*.{ts,tsx}', { + .sync('{app,ts}/**/*.{ts,tsx}', { nodir: true, root: ROOT_DIR, }) diff --git a/sticker-creator/_mixins.scss b/sticker-creator/_mixins.scss deleted file mode 100644 index 01b502c6596d..000000000000 --- a/sticker-creator/_mixins.scss +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@mixin light-theme() { - @content; -} - -@mixin dark-theme() { - :global(.dark-theme) & { - @content; - } -} diff --git a/sticker-creator/app/index.scss b/sticker-creator/app/index.scss deleted file mode 100644 index fca5e596aa56..000000000000 --- a/sticker-creator/app/index.scss +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../mixins'; -@import '../../stylesheets/variables'; - -.container { - display: grid; - height: var(--window-height); - grid-template-rows: 47px calc(var(--window-height) - 47px - 68px) 68px; - - @include light-theme() { - background-color: $color-white; - } - - @include dark-theme() { - background-color: $color-gray-90; - } -} diff --git a/sticker-creator/app/index.tsx b/sticker-creator/app/index.tsx deleted file mode 100644 index a4d844156da0..000000000000 --- a/sticker-creator/app/index.tsx +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { Redirect, Route, Switch } from 'react-router-dom'; -import { DropStage } from './stages/DropStage'; -import { EmojiStage } from './stages/EmojiStage'; -import { UploadStage } from './stages/UploadStage'; -import { MetaStage } from './stages/MetaStage'; -import { ShareStage } from './stages/ShareStage'; -import * as styles from './index.scss'; -import { PageHeader } from '../elements/PageHeader'; -import { useI18n } from '../util/i18n'; -import { TitleBarContainer } from '../../ts/components/TitleBarContainer'; -import type { ExecuteMenuRoleType } from '../../ts/components/TitleBarContainer'; -import { useTheme } from '../../ts/hooks/useTheme'; - -export type AppPropsType = Readonly<{ - executeMenuRole: ExecuteMenuRoleType; - hasCustomTitleBar: boolean; -}>; - -export function App({ - executeMenuRole, - hasCustomTitleBar, -}: AppPropsType): JSX.Element { - const i18n = useI18n(); - const theme = useTheme(); - - return ( - -
- {i18n('StickerCreator--title')} - - - - - - - - - - - - - - - - - - -
-
- ); -} diff --git a/sticker-creator/app/stages/AppStage.scss b/sticker-creator/app/stages/AppStage.scss deleted file mode 100644 index 6d2da47c3c4d..000000000000 --- a/sticker-creator/app/stages/AppStage.scss +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -.padded { - padding: 0 16px; -} - -.main { - composes: padded; - padding-top: 16px; - display: grid; - height: 100%; - grid-template-rows: 26px 36px calc(100% - 26px - 36px); - overflow: auto; -} - -.no-message { - composes: main; - grid-template-rows: 26px calc(100% - 26px); -} - -.empty { - composes: main; - grid-template-rows: 100%; -} - -.footer { - composes: padded; - display: flex; - flex-direction: row; - justify-content: flex-end; - align-items: center; -} - -.footer-right { - display: flex; - flex-direction: row; - align-items: center; -} - -.button { - margin-left: 12px; -} - -.toaster { - position: fixed; - bottom: 16px; - left: 50%; - transform: translate(-50%, 0px); -} diff --git a/sticker-creator/app/stages/AppStage.tsx b/sticker-creator/app/stages/AppStage.tsx deleted file mode 100644 index 642e7ea9aaae..000000000000 --- a/sticker-creator/app/stages/AppStage.tsx +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import React from 'react'; -import * as styles from './AppStage.scss'; -import { history } from '../../util/history'; -import { Button } from '../../elements/Button'; -import { useI18n } from '../../util/i18n'; -import { Text } from '../../elements/Typography'; -import { Toaster } from '../../components/Toaster'; -import { stickersDuck } from '../../store'; - -export type Props = { - readonly children: React.ReactNode; - readonly empty?: boolean; - readonly prev?: string; - readonly prevText?: string; - readonly next?: string; - readonly nextActive?: boolean; - readonly noMessage?: boolean; - readonly onNext?: () => unknown; - readonly onPrev?: () => unknown; - readonly nextText?: string; -}; - -const getClassName = ({ noMessage, empty }: Props) => { - if (noMessage) { - return styles.noMessage; - } - - if (empty) { - return styles.empty; - } - - return styles.main; -}; - -export function AppStage(props: Props): JSX.Element { - const { - children, - next, - nextActive, - nextText, - onNext, - onPrev, - prev, - prevText, - } = props; - const i18n = useI18n(); - - const handleNext = React.useCallback(() => { - if (next) { - history.push(next); - } - }, [next]); - - const handlePrev = React.useCallback(() => { - if (prev) { - history.push(prev); - } - }, [prev]); - - const addMoreCount = stickersDuck.useAddMoreCount(); - const toasts = stickersDuck.useToasts(); - const { dismissToast } = stickersDuck.useStickerActions(); - - return ( - <> -
{children}
-
- {prev || onPrev ? ( - - ) : null} - {addMoreCount > 0 ? ( - - {i18n('icu:StickerCreator--DropStage--addMore', { - count: addMoreCount, - })} - - ) : null} - {next || onNext ? ( - - ) : null} -
- ({ - id, - // eslint-disable-next-line local-rules/valid-i18n-keys - text: i18n(slice.key, slice.subs), - }))} - onDismiss={dismissToast} - /> - - ); -} diff --git a/sticker-creator/app/stages/DropStage.scss b/sticker-creator/app/stages/DropStage.scss deleted file mode 100644 index d7d6ddff9056..000000000000 --- a/sticker-creator/app/stages/DropStage.scss +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -.message { - max-width: 450px; -} - -.main { - flex-grow: 1; - margin-top: 16px; - display: flex; - flex-direction: column; -} - -.info { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: flex-start; -} - -.sticker-grid { - display: grid; - grid-template-columns: repeat(auto-fill, 186px); - grid-gap: 8px; - justify-content: center; -} diff --git a/sticker-creator/app/stages/DropStage.tsx b/sticker-creator/app/stages/DropStage.tsx deleted file mode 100644 index 51d123f5c290..000000000000 --- a/sticker-creator/app/stages/DropStage.tsx +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { AppStage } from './AppStage'; -import * as styles from './DropStage.scss'; -import { H2, Text } from '../../elements/Typography'; -import { LabeledCheckbox } from '../../elements/LabeledCheckbox'; -import { StickerGrid } from '../../components/StickerGrid'; -import { stickersDuck } from '../../store'; -import { useI18n } from '../../util/i18n'; - -export function DropStage(): JSX.Element { - const i18n = useI18n(); - const stickerPaths = stickersDuck.useStickerOrder(); - const stickersReady = stickersDuck.useStickersReady(); - const haveStickers = stickerPaths.length > 0; - const [showGuide, setShowGuide] = React.useState(true); - const { resetStatus } = stickersDuck.useStickerActions(); - - React.useEffect(() => { - resetStatus(); - }, [resetStatus]); - - return ( - -

{i18n('icu:StickerCreator--DropStage--title')}

-
- - {i18n('StickerCreator--DropStage--help')} - - {haveStickers ? ( - - {i18n('StickerCreator--DropStage--showMargins')} - - ) : null} -
-
- -
-
- ); -} diff --git a/sticker-creator/app/stages/EmojiStage.tsx b/sticker-creator/app/stages/EmojiStage.tsx deleted file mode 100644 index 115154313332..000000000000 --- a/sticker-creator/app/stages/EmojiStage.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { AppStage } from './AppStage'; -import * as styles from './DropStage.scss'; -import { H2, Text } from '../../elements/Typography'; -import { StickerGrid } from '../../components/StickerGrid'; -import { stickersDuck } from '../../store'; -import { useI18n } from '../../util/i18n'; - -export function EmojiStage(): JSX.Element { - const i18n = useI18n(); - const emojisReady = stickersDuck.useEmojisReady(); - - return ( - -

{i18n('StickerCreator--EmojiStage--title')}

-
- - {i18n('StickerCreator--EmojiStage--help')} - -
-
- -
-
- ); -} diff --git a/sticker-creator/app/stages/MetaStage.scss b/sticker-creator/app/stages/MetaStage.scss deleted file mode 100644 index 33d0ef1c85fd..000000000000 --- a/sticker-creator/app/stages/MetaStage.scss +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../../stylesheets/variables'; -@import '../../mixins'; - -.main { - display: flex; - flex-direction: column; - align-items: center; -} - -.row { - margin-bottom: 18px; - width: 448px; -} - -.cover-container { - display: flex; - flex-direction: row; - justify-content: center; - padding: 18px; -} - -.label { - user-select: none; - font-size: 13px; - font-family: $inter; - font-weight: 500; - margin: 0; - - @include light-theme() { - color: $color-gray-90; - } - - @include dark-theme() { - color: $color-white; - } -} - -.cover-image { - width: 178px; - height: 178px; -} - -.cover-frame { - composes: cover-image; - overflow: hidden; - - border: { - radius: 4px; - style: solid; - width: 1px; - } - - @include light-theme() { - border-color: $color-gray-60; - } - - @include dark-theme() { - border-color: $color-gray-25; - } -} - -.cover-frame-active { - composes: cover-frame; - - @include light-theme() { - border-color: $color-ultramarine; - } - - @include dark-theme() { - border-color: $color-ultramarine-light; - } -} diff --git a/sticker-creator/app/stages/MetaStage.tsx b/sticker-creator/app/stages/MetaStage.tsx deleted file mode 100644 index 9885bafb6a62..000000000000 --- a/sticker-creator/app/stages/MetaStage.tsx +++ /dev/null @@ -1,102 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import type { FileWithPath } from 'react-dropzone'; -import { AppStage } from './AppStage'; -import * as styles from './MetaStage.scss'; -import { processStickerImage } from '../../util/preload'; -import { useStickerDropzone } from '../../util/useStickerDropzone'; -import { history } from '../../util/history'; -import { H2, Text } from '../../elements/Typography'; -import { LabeledInput } from '../../elements/LabeledInput'; -import { ConfirmModal } from '../../components/ConfirmModal'; -import { stickersDuck } from '../../store'; -import { useI18n } from '../../util/i18n'; - -export function MetaStage(): JSX.Element { - const i18n = useI18n(); - const actions = stickersDuck.useStickerActions(); - const valid = stickersDuck.useAllDataValid(); - const cover = stickersDuck.useCover(); - const title = stickersDuck.useTitle(); - const author = stickersDuck.useAuthor(); - const [confirming, setConfirming] = React.useState(false); - - const onDrop = React.useCallback( - async ([{ path }]: Array) => { - try { - const stickerImage = await processStickerImage(path); - actions.setCover(stickerImage); - } catch (e) { - actions.removeSticker(path); - } - }, - [actions] - ); - - const { getRootProps, getInputProps, isDragActive } = - useStickerDropzone(onDrop); - - const onNext = React.useCallback(() => { - setConfirming(true); - }, [setConfirming]); - - const onCancel = React.useCallback(() => { - setConfirming(false); - }, [setConfirming]); - - const onConfirm = React.useCallback(() => { - history.push('/upload'); - }, []); - - const coverFrameClass = isDragActive - ? styles.coverFrameActive - : styles.coverFrame; - - return ( - - {confirming ? ( - - {i18n('StickerCreator--MetaStage--ConfirmDialog--text')} - - ) : null} -

{i18n('StickerCreator--MetaStage--title')}

-
-
- - {i18n('StickerCreator--MetaStage--Field--title')} - -
-
- - {i18n('StickerCreator--MetaStage--Field--author')} - -
-
-

- {i18n('StickerCreator--MetaStage--Field--cover')} -

- {i18n('StickerCreator--MetaStage--Field--cover--help')} -
-
- {cover?.src ? ( - Cover - ) : null} - -
-
-
-
-
- ); -} diff --git a/sticker-creator/app/stages/ShareStage.scss b/sticker-creator/app/stages/ShareStage.scss deleted file mode 100644 index b3be78b06b01..000000000000 --- a/sticker-creator/app/stages/ShareStage.scss +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../../stylesheets/variables'; -@import '../../mixins'; - -.main { - display: flex; - flex-direction: column; - align-items: center; -} - -.message { - max-width: 450px; -} - -.call-to-action { - max-width: 500px; -} - -.row { - margin-bottom: 18px; - display: flex; - flex-direction: row; - justify-content: center; - flex-shrink: 0; -} diff --git a/sticker-creator/app/stages/ShareStage.tsx b/sticker-creator/app/stages/ShareStage.tsx deleted file mode 100644 index ee2f70da0ff5..000000000000 --- a/sticker-creator/app/stages/ShareStage.tsx +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { AppStage } from './AppStage'; -import * as styles from './ShareStage.scss'; -import * as appStyles from './AppStage.scss'; -import { history } from '../../util/history'; -import { H2, Text } from '../../elements/Typography'; -import { CopyText } from '../../elements/CopyText'; -import { Toast } from '../../elements/Toast'; -import { ShareButtons } from '../../components/ShareButtons'; -import { StickerPackPreview } from '../../components/StickerPackPreview'; -import { stickersDuck } from '../../store'; -import { useI18n } from '../../util/i18n'; -import { Intl } from '../../../ts/components/Intl'; - -export function ShareStage(): JSX.Element { - const i18n = useI18n(); - const actions = stickersDuck.useStickerActions(); - const title = stickersDuck.useTitle(); - const author = stickersDuck.useAuthor(); - const images = stickersDuck.useOrderedImagePaths(); - const shareUrl = stickersDuck.usePackUrl(); - const [linkCopied, setLinkCopied] = React.useState(false); - const onCopy = React.useCallback(() => { - setLinkCopied(true); - }, [setLinkCopied]); - const resetLinkCopied = React.useCallback(() => { - setLinkCopied(false); - }, [setLinkCopied]); - - const handleNext = React.useCallback(() => { - window.close(); - }, []); - - const handlePrev = React.useCallback(() => { - actions.reset(); - history.push('/'); - }, [actions]); - - return ( - - {shareUrl ? ( - <> -

{i18n('StickerCreator--ShareStage--title')}

- - {i18n('StickerCreator--ShareStage--help')} - -
-
- -
-
- -
-
- - #makeprivacystick, - ]} - /> - -
-
- -
-
- {linkCopied ? ( -
- - {i18n('StickerCreator--Toasts--linkedCopied')} - -
- ) : null} - - ) : null} -
- ); -} diff --git a/sticker-creator/app/stages/UploadStage.scss b/sticker-creator/app/stages/UploadStage.scss deleted file mode 100644 index f720d91a05d8..000000000000 --- a/sticker-creator/app/stages/UploadStage.scss +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -.base { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; -} - -.progress { - margin: 24px 0; -} diff --git a/sticker-creator/app/stages/UploadStage.tsx b/sticker-creator/app/stages/UploadStage.tsx deleted file mode 100644 index 7bed41a7a126..000000000000 --- a/sticker-creator/app/stages/UploadStage.tsx +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { noop } from 'lodash'; -import { AppStage } from './AppStage'; -import * as styles from './UploadStage.scss'; -import { history } from '../../util/history'; -import { ProgressBar } from '../../elements/ProgressBar'; -import { H2, Text } from '../../elements/Typography'; -import { Button } from '../../elements/Button'; -import { stickersDuck } from '../../store'; -import { encryptAndUpload } from '../../util/preload'; -import { useI18n } from '../../util/i18n'; -import * as Errors from '../../../ts/types/errors'; - -const handleCancel = () => { - history.push('/add-meta'); -}; - -export function UploadStage(): JSX.Element { - const i18n = useI18n(); - const actions = stickersDuck.useStickerActions(); - const cover = stickersDuck.useCover(); - const title = stickersDuck.useTitle(); - const author = stickersDuck.useAuthor(); - const orderedData = stickersDuck.useSelectOrderedData(); - const total = orderedData.length; - const [complete, setComplete] = React.useState(0); - - React.useEffect(() => { - void (async () => { - const onProgress = () => { - setComplete(i => i + 1); - }; - try { - if (!cover) { - throw new Error('UploadStage: Cover was missing on upload!'); - } - const packMeta = await encryptAndUpload( - { title, author }, - orderedData, - cover, - onProgress - ); - actions.setPackMeta(packMeta); - history.push('/share'); - } catch (e) { - window.SignalContext.log.error( - 'Error uploading pack:', - Errors.toLogFormat(e) - ); - actions.addToast({ - key: 'StickerCreator--Toasts--errorUploading', - subs: { message: e.message }, - }); - history.push('/add-meta'); - } - })(); - - return noop; - }, [actions, title, author, cover, orderedData]); - - return ( - -
-

{i18n('StickerCreator--UploadStage--title')}

- - {i18n('StickerCreator--UploadStage-uploaded', { - // We convert these to string so that 0 isn't falsy, which i18n checks for. - count: String(complete), - total: String(total), - })} - - - -
-
- ); -} diff --git a/sticker-creator/components/ConfirmModal.scss b/sticker-creator/components/ConfirmModal.scss deleted file mode 100644 index 65e91de0b033..000000000000 --- a/sticker-creator/components/ConfirmModal.scss +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -.facade { - background: rgba(0, 0, 0, 0.33); - width: var(--window-width); - height: var(--window-height); - display: flex; - justify-content: center; - align-items: center; - position: fixed; - left: var(--window-border); - top: var(--titlebar-height); -} diff --git a/sticker-creator/components/ConfirmModal.tsx b/sticker-creator/components/ConfirmModal.tsx deleted file mode 100644 index 10eccb4b7e66..000000000000 --- a/sticker-creator/components/ConfirmModal.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { createPortal } from 'react-dom'; -import * as styles from './ConfirmModal.scss'; -import type { Props } from '../elements/ConfirmDialog'; -import { ConfirmDialog } from '../elements/ConfirmDialog'; - -export type Mode = 'removable' | 'pick-emoji' | 'add'; - -export const ConfirmModal = React.memo(function ConfirmModalInner( - props: Props -) { - const { onCancel } = props; - const [popperRoot, setPopperRoot] = React.useState(); - - // Create popper root and handle outside clicks - React.useEffect(() => { - const root = document.createElement('div'); - setPopperRoot(root); - document.body.appendChild(root); - const handleOutsideClick = ({ target }: MouseEvent) => { - if (!root.contains(target as Node)) { - onCancel(); - } - }; - document.addEventListener('click', handleOutsideClick); - - return () => { - document.body.removeChild(root); - document.removeEventListener('click', handleOutsideClick); - }; - }, [onCancel]); - - return popperRoot - ? createPortal( -
- -
, - popperRoot - ) - : null; -}); diff --git a/sticker-creator/components/ShareButtons.scss b/sticker-creator/components/ShareButtons.scss deleted file mode 100644 index 3b0ff7aaf1d1..000000000000 --- a/sticker-creator/components/ShareButtons.scss +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; -@import '../mixins'; - -.container { - display: flex; - justify-content: center; -} - -.text { - @include light-theme() { - border: 1px solid $color-gray-15; - color: $color-gray-90; - } - - @include dark-theme() { - border: 1px solid $color-gray-60; - color: $color-white; - } -} - -.button { - width: 32px; - height: 32px; - background: transparent; - border: none; - margin-left: 12px; -} diff --git a/sticker-creator/components/ShareButtons.stories.tsx b/sticker-creator/components/ShareButtons.stories.tsx deleted file mode 100644 index 8f9717200ed3..000000000000 --- a/sticker-creator/components/ShareButtons.stories.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; - -import { StoryRow } from '../elements/StoryRow'; -import { ShareButtons } from './ShareButtons'; - -export default { - title: 'Sticker Creator/components', -}; - -export const _ShareButtons = (): JSX.Element => { - const value = text('value', 'https://signal.org'); - - return ( - - - - ); -}; - -_ShareButtons.story = { - name: 'ShareButtons', -}; diff --git a/sticker-creator/components/ShareButtons.tsx b/sticker-creator/components/ShareButtons.tsx deleted file mode 100644 index bf0fc49e3c30..000000000000 --- a/sticker-creator/components/ShareButtons.tsx +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -/* eslint-disable max-len */ - -import * as React from 'react'; -import * as styles from './ShareButtons.scss'; -import { useI18n } from '../util/i18n'; - -export type Props = { - value: string; -}; - -export const ShareButtons: React.ComponentType = React.memo( - function ShareButtonsInner({ value }) { - const i18n = useI18n(); - - const buttonPaths = React.useMemo< - Array<[string, string, string, string]> - >(() => { - const packUrl = encodeURIComponent(value); - const text = encodeURIComponent( - `${i18n('StickerCreator--ShareStage--socialMessage')} ${value}` - ); - - return [ - // Facebook - [ - i18n('StickerCreator--ShareButtons--facebook'), - '#4267B2', - 'M20.155 10.656l-1.506.001c-1.181 0-1.41.561-1.41 1.384v1.816h2.817l-.367 2.845h-2.45V24h-2.937v-7.298h-2.456v-2.845h2.456V11.76c0-2.435 1.487-3.76 3.658-3.76 1.04 0 1.934.077 2.195.112v2.544z', - `https://www.facebook.com/sharer/sharer.php?u=${packUrl}`, - ], - // Twitter - [ - i18n('StickerCreator--ShareButtons--twitter'), - '#1CA1F2', - 'M22.362 12.737c.006.141.01.282.01.425 0 4.337-3.302 9.339-9.34 9.339A9.294 9.294 0 018 21.027c.257.03.518.045.783.045a6.584 6.584 0 004.077-1.405 3.285 3.285 0 01-3.067-2.279 3.312 3.312 0 001.483-.057 3.283 3.283 0 01-2.633-3.218v-.042c.442.246.949.394 1.487.411a3.282 3.282 0 01-1.016-4.383 9.32 9.32 0 006.766 3.43 3.283 3.283 0 015.593-2.994 6.568 6.568 0 002.085-.796 3.299 3.299 0 01-1.443 1.816A6.587 6.587 0 0024 11.038a6.682 6.682 0 01-1.638 1.699', - `https://twitter.com/intent/tweet?text=${text}`, - ], - // Pinterest - // [ - // i18n('StickerCreator--ShareButtons--pinterest'), - // '#BD081C', - // 'M17.234 19.563c-.992 0-1.926-.536-2.245-1.146 0 0-.534 2.118-.646 2.527-.398 1.444-1.569 2.889-1.66 3.007-.063.083-.203.057-.218-.052-.025-.184-.324-2.007.028-3.493l1.182-5.008s-.293-.587-.293-1.454c0-1.362.789-2.379 1.772-2.379.836 0 1.239.628 1.239 1.38 0 .84-.535 2.097-.811 3.261-.231.975.489 1.77 1.451 1.77 1.74 0 2.913-2.236 2.913-4.886 0-2.014-1.356-3.522-3.824-3.522-2.787 0-4.525 2.079-4.525 4.402 0 .8.237 1.365.607 1.802.17.201.194.282.132.512-.045.17-.145.576-.188.738-.061.233-.249.316-.46.23-1.283-.524-1.882-1.931-1.882-3.511C9.806 11.13 12.008 8 16.374 8c3.51 0 5.819 2.538 5.819 5.265 0 3.605-2.005 6.298-4.959 6.298', - // `https://pinterest.com/pin/create/button/?url=${packUrl}`, - // ], - // Whatsapp - [ - i18n('StickerCreator--ShareButtons--whatsapp'), - '#25D366', - 'M16.033 23.862h-.003a7.914 7.914 0 01-3.79-.965L8.035 24l1.126-4.109a7.907 7.907 0 01-1.059-3.964C8.104 11.556 11.661 8 16.033 8c2.121 0 4.113.826 5.61 2.325a7.878 7.878 0 012.321 5.609c-.002 4.371-3.56 7.928-7.931 7.928zm3.88-5.101c-.165.463-.957.885-1.338.942a2.727 2.727 0 01-1.248-.078 11.546 11.546 0 01-1.13-.418c-1.987-.858-3.286-2.859-3.385-2.991-.1-.132-.81-1.074-.81-2.049 0-.975.513-1.455.695-1.653a.728.728 0 01.528-.248c.132 0 .264.001.38.007.122.006.285-.046.446.34.165.397.56 1.372.61 1.471.05.099.083.215.017.347-.066.132-.1.215-.198.331-.1.115-.208.258-.297.347-.1.098-.203.206-.087.404.116.198.513.847 1.102 1.372.757.675 1.396.884 1.594.984.198.099.314.082.429-.05.116-.132.496-.578.628-.777.132-.198.264-.165.446-.099.18.066 1.156.545 1.354.645.198.099.33.148.38.231.049.083.049.479-.116.942zm-3.877-9.422c-3.636 0-6.594 2.956-6.595 6.589 0 1.245.348 2.458 1.008 3.507l.157.249-.666 2.432 2.495-.654.24.142a6.573 6.573 0 003.355.919h.003a6.6 6.6 0 006.592-6.59 6.55 6.55 0 00-1.93-4.662 6.549 6.549 0 00-4.66-1.932z', - `https://wa.me?text=${text}`, - ], - ]; - }, [i18n, value]); - - return ( -
- {buttonPaths.map(([title, fill, path, url]) => ( - - ))} -
- ); - } -); diff --git a/sticker-creator/components/StickerFrame.scss b/sticker-creator/components/StickerFrame.scss deleted file mode 100644 index 039e98717ade..000000000000 --- a/sticker-creator/components/StickerFrame.scss +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../mixins'; -@import '../../stylesheets/variables'; - -$width: 186px; -$height: 186px; -$guide-offset: 6px; -$border-width: 1px; - -.container { - position: relative; - width: $width; - height: $height; - border: { - radius: 4px; - width: $border-width; - style: solid; - } - overflow: hidden; - user-select: none; - - @include light-theme() { - border-color: $color-gray-25; - background: $color-white; - } - - @include dark-theme() { - border-color: $color-gray-60; - background: $color-gray-90; - } -} - -.dragActive { - composes: container; - - @include light-theme() { - border-color: $color-ultramarine; - } - - @include dark-theme() { - border-color: $color-ultramarine-light; - } -} - -.image { - width: $width; - height: $height; -} - -@keyframes spin { - to { - transform: rotate(360deg); - } -} - -.spinner { - composes: image; - animation: spin 1s linear infinite; - display: flex; - justify-content: center; - align-items: center; - - @include light-theme() { - color: $color-gray-25; - } - - @include dark-theme() { - color: $color-gray-60; - } -} - -.guide { - width: $width - (2 * $guide-offset); - height: $height - (2 * $guide-offset); - position: absolute; - left: $guide-offset - $border-width; - top: $guide-offset - $border-width; - border: { - radius: 0px; - width: $border-width; - style: dashed; - } - pointer-events: none; - - @include light-theme() { - border-color: $color-gray-25; - } - - @include dark-theme() { - border-color: $color-gray-60; - } -} - -.close-button { - width: 16px; - height: 16px; - position: absolute; - display: flex; - justify-content: center; - align-items: center; - top: 8px; - right: 8px; - font-family: $inter; - border: none; - background: none; - padding: 0; - - &-icon { - @include light-theme() { - color: $color-black; - } - @include dark-theme() { - color: $color-white; - } - } -} - -.emoji-button { - width: 41px; - height: 28px; - position: absolute; - top: 6px; - right: 6px; - border: none; - border-radius: 13.5px; - padding: 0; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - - @include light-theme() { - background-color: $color-gray-05; - color: $color-gray-90; - } - - @include dark-theme() { - background-color: $color-gray-75; - color: rgba(255, 255, 255, 0.75); - } -} diff --git a/sticker-creator/components/StickerFrame.stories.tsx b/sticker-creator/components/StickerFrame.stories.tsx deleted file mode 100644 index b616ebd40705..000000000000 --- a/sticker-creator/components/StickerFrame.stories.tsx +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { boolean, select, text } from '@storybook/addon-knobs'; -import { action } from '@storybook/addon-actions'; - -import { StoryRow } from '../elements/StoryRow'; -import { StickerFrame } from './StickerFrame'; - -import type { EmojiPickDataType } from '../../ts/components/emoji/EmojiPicker'; - -export default { - title: 'Sticker Creator/components', -}; - -export const _StickerFrame = (): JSX.Element => { - const image = text('image url', '/fixtures/512x515-thumbs-up-lincoln.webp'); - const showGuide = boolean('show guide', true); - const mode = select('mode', ['removable', 'pick-emoji', 'add'], 'add'); - const onRemove = action('onRemove'); - const onDrop = action('onDrop'); - const [skinTone, setSkinTone] = React.useState(0); - const [emoji, setEmoji] = React.useState( - undefined - ); - - return ( - - setEmoji(e.emoji)} - onDrop={onDrop} - /> - - ); -}; - -_StickerFrame.story = { - name: 'StickerFrame, add sticker', -}; - -export function EmojiSelectMode(): JSX.Element { - const image = text('image url', '/fixtures/512x515-thumbs-up-lincoln.webp'); - const setSkinTone = action('setSkinTone'); - const onRemove = action('onRemove'); - const onDrop = action('onDrop'); - const [emoji, setEmoji] = React.useState( - undefined - ); - - return ( - - setEmoji(e.emoji)} - onDrop={onDrop} - /> - - ); -} - -EmojiSelectMode.story = { - name: 'StickerFrame, emoji select mode', -}; diff --git a/sticker-creator/components/StickerFrame.tsx b/sticker-creator/components/StickerFrame.tsx deleted file mode 100644 index 12ab0f2079ed..000000000000 --- a/sticker-creator/components/StickerFrame.tsx +++ /dev/null @@ -1,304 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { createPortal } from 'react-dom'; -import { SortableHandle } from 'react-sortable-hoc'; -import { noop } from 'lodash'; -import { - Manager as PopperManager, - Popper, - Reference as PopperReference, -} from 'react-popper'; -import { AddEmoji } from '../elements/icons'; -import type { Props as DropZoneProps } from '../elements/DropZone'; -import { DropZone } from '../elements/DropZone'; -import { StickerPreview } from '../elements/StickerPreview'; -import * as styles from './StickerFrame.scss'; -import type { - EmojiPickDataType, - Props as EmojiPickerProps, -} from '../../ts/components/emoji/EmojiPicker'; -import { EmojiPicker } from '../../ts/components/emoji/EmojiPicker'; -import { Emoji } from '../../ts/components/emoji/Emoji'; -import { PopperRootContext } from '../../ts/components/PopperRootContext'; -import { useI18n } from '../util/i18n'; - -export type Mode = 'removable' | 'pick-emoji' | 'add'; - -export type Props = Partial< - Pick -> & - Partial> & { - readonly id?: string; - readonly emojiData?: EmojiPickDataType; - readonly image?: string; - readonly mode?: Mode; - readonly showGuide?: boolean; - onPickEmoji?({ - id, - emoji, - }: { - id: string; - emoji: EmojiPickDataType; - }): unknown; - onRemove?(id: string): unknown; - }; - -const spinnerSvg = ( - - - -); - -const closeSvg = ( - - - -); - -const ImageHandle = SortableHandle((props: { src: string }) => ( - Sticker -)); - -export const StickerFrame = React.memo(function StickerFrameInner({ - id, - emojiData, - image, - showGuide, - mode, - onRemove, - onPickEmoji, - skinTone, - onSetSkinTone, - onDrop, -}: Props) { - const i18n = useI18n(); - const [emojiPickerOpen, setEmojiPickerOpen] = React.useState(false); - const [emojiPopperRoot, setEmojiPopperRoot] = - React.useState(null); - const [previewActive, setPreviewActive] = React.useState(false); - const [previewPopperRoot, setPreviewPopperRoot] = - React.useState(null); - const timerRef = React.useRef(); - - const handleToggleEmojiPicker = React.useCallback(() => { - setEmojiPickerOpen(open => !open); - }, [setEmojiPickerOpen]); - - const handlePickEmoji = React.useCallback( - (emoji: EmojiPickDataType) => { - if (!id) { - return; - } - if (!onPickEmoji) { - throw new Error( - 'StickerFrame/handlePickEmoji: onPickEmoji was not provided!' - ); - } - onPickEmoji({ id, emoji }); - setEmojiPickerOpen(false); - }, - [id, onPickEmoji, setEmojiPickerOpen] - ); - - const handleRemove = React.useCallback(() => { - if (!id) { - return; - } - if (!onRemove) { - throw new Error('StickerFrame/handleRemove: onRemove was not provided!'); - } - onRemove(id); - }, [onRemove, id]); - - const handleMouseEnter = React.useCallback(() => { - window.clearTimeout(timerRef.current); - timerRef.current = window.setTimeout(() => { - setPreviewActive(true); - }, 500); - }, [timerRef, setPreviewActive]); - - const handleMouseLeave = React.useCallback(() => { - clearTimeout(timerRef.current); - setPreviewActive(false); - }, [timerRef, setPreviewActive]); - - React.useEffect( - () => () => { - clearTimeout(timerRef.current); - }, - [timerRef] - ); - - const { createRoot, removeRoot } = React.useContext(PopperRootContext); - - // Create popper root and handle outside clicks - React.useEffect(() => { - if (emojiPickerOpen) { - const root = createRoot(); - setEmojiPopperRoot(root); - const handleOutsideClick = ({ target }: MouseEvent) => { - if (!root.contains(target as Node)) { - setEmojiPickerOpen(false); - } - }; - document.addEventListener('click', handleOutsideClick); - - return () => { - removeRoot(root); - setEmojiPopperRoot(null); - document.removeEventListener('click', handleOutsideClick); - }; - } - - return noop; - }, [ - createRoot, - emojiPickerOpen, - removeRoot, - setEmojiPickerOpen, - setEmojiPopperRoot, - ]); - - React.useEffect(() => { - if (mode !== 'pick-emoji' && image && previewActive) { - const root = createRoot(); - setPreviewPopperRoot(root); - - return () => { - removeRoot(root); - }; - } - - return noop; - }, [ - createRoot, - image, - mode, - previewActive, - removeRoot, - setPreviewPopperRoot, - ]); - - const [dragActive, setDragActive] = React.useState(false); - const containerClass = dragActive ? styles.dragActive : styles.container; - - return ( - - - {({ ref: rootRef }) => ( -
- { - // eslint-disable-next-line no-nested-ternary - mode !== 'add' ? ( - image ? ( - - ) : ( -
{spinnerSvg}
- ) - ) : null - } - {showGuide && mode !== 'add' ? ( -
- ) : null} - {mode === 'add' && onDrop ? ( - - ) : null} - {mode === 'removable' ? ( - - ) : null} - {mode === 'pick-emoji' ? ( - - - {({ ref }) => ( - - )} - - {emojiPickerOpen && emojiPopperRoot - ? createPortal( - - {({ ref, style }) => ( - - )} - , - emojiPopperRoot - ) - : null} - - ) : null} - {mode !== 'pick-emoji' && - image && - previewActive && - previewPopperRoot - ? createPortal( - - {({ ref, style, arrowProps, placement }) => ( - - )} - , - previewPopperRoot - ) - : null} -
- )} - - - ); -}); diff --git a/sticker-creator/components/StickerGrid.scss b/sticker-creator/components/StickerGrid.scss deleted file mode 100644 index d7bc2df2ce90..000000000000 --- a/sticker-creator/components/StickerGrid.scss +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -.grid { - display: grid; - grid-template-columns: repeat(auto-fill, 186px); - grid-template-rows: repeat(auto-fill, 186px); - grid-gap: 8px; - justify-content: center; -} - -.drop { - display: flex; - flex-direction: column; - flex-grow: 1; -} diff --git a/sticker-creator/components/StickerGrid.tsx b/sticker-creator/components/StickerGrid.tsx deleted file mode 100644 index 1dbcf735d629..000000000000 --- a/sticker-creator/components/StickerGrid.tsx +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import PQueue from 'p-queue'; -import type { SortEndHandler } from 'react-sortable-hoc'; -import { SortableContainer, SortableElement } from 'react-sortable-hoc'; -import * as styles from './StickerGrid.scss'; -import type { Props as StickerFrameProps } from './StickerFrame'; -import { StickerFrame } from './StickerFrame'; -import { stickersDuck } from '../store'; -import type { Props as DropZoneProps } from '../elements/DropZone'; -import { DropZone } from '../elements/DropZone'; -import { processStickerImage } from '../util/preload'; -import { useI18n } from '../util/i18n'; -import { MINUTE } from '../../ts/util/durations'; -import { drop } from '../../ts/util/drop'; -import * as Errors from '../../ts/types/errors'; - -const queue = new PQueue({ concurrency: 3, timeout: MINUTE * 30 }); - -type SmartStickerFrameProps = Omit & { id: string }; - -const SmartStickerFrame = SortableElement( - ({ id, showGuide, mode }: SmartStickerFrameProps) => { - const data = stickersDuck.useStickerData(id); - const actions = stickersDuck.useStickerActions(); - const image = data.imageData ? data.imageData.src : undefined; - - return ( - - ); - } -); - -export type Props = Pick; - -export type InnerGridProps = Props & { - ids: Array; -}; - -const InnerGrid = SortableContainer( - ({ ids, mode, showGuide }: InnerGridProps) => { - const i18n = useI18n(); - const containerClassName = ids.length > 0 ? styles.grid : styles.drop; - const frameMode = mode === 'add' ? 'removable' : 'pick-emoji'; - - const actions = stickersDuck.useStickerActions(); - - const handleDrop = React.useCallback( - async paths => { - actions.initializeStickers(paths); - paths.forEach(path => { - drop( - queue.add(async () => { - try { - const stickerImage = await processStickerImage(path); - actions.addImageData(stickerImage); - } catch (e) { - window.SignalContext.log.error( - 'Error processing image:', - Errors.toLogFormat(e) - ); - actions.removeSticker(path); - - const key = - e instanceof window.ProcessStickerImageError - ? e.errorMessageI18nKey - : 'StickerCreator--Toasts--errorProcessing'; - actions.addToast({ - key, - }); - } - }) - ); - }); - }, - [actions] - ); - - return ( -
- {ids.length > 0 ? ( - <> - {ids.map((p, i) => ( - - ))} - {mode === 'add' && ids.length < stickersDuck.maxStickers ? ( - - ) : null} - - ) : ( - - )} -
- ); - } -); - -export const StickerGrid = SortableContainer((props: Props) => { - const ids = stickersDuck.useStickerOrder(); - const actions = stickersDuck.useStickerActions(); - const handleSortEnd = React.useCallback( - sortEnd => { - actions.moveSticker(sortEnd); - }, - [actions] - ); - - return ( - - ); -}); diff --git a/sticker-creator/components/StickerPackPreview.scss b/sticker-creator/components/StickerPackPreview.scss deleted file mode 100644 index 53cdc2ea8eb9..000000000000 --- a/sticker-creator/components/StickerPackPreview.scss +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../mixins'; -@import '../../stylesheets/variables'; - -@mixin background() { - @include light-theme() { - background: $color-white; - } - - @include dark-theme() { - background: $color-gray-75; - } -} - -.container { - position: relative; - width: 330px; - height: 270px; - border-radius: 3px; - overflow: hidden; - box-shadow: 0 3px 9px 0px rgba(0, 0, 0, 0.2); - @include background(); -} - -.title-bar { - height: 27px; - padding: 0 12px; - display: flex; - flex-direction: row; - align-items: center; - font: { - family: $inter; - size: 10.5px; - weight: 500; - } - - @include background(); - - @include light-theme { - color: $color-gray-90; - } - - @include dark-theme { - color: $color-gray-05; - } -} - -.scroller { - height: calc(100% - 27px); - padding-bottom: 57px; - overflow: auto; -} - -.grid { - display: grid; - grid-gap: 6px; - padding: 0 16px 0 12px; - grid-template-columns: repeat(4, 1fr); - overflow: auto; - justify-items: center; -} - -.sticker { - width: 72px; - height: 72px; -} - -.meta { - width: 306px; - height: 39px; - border-radius: 3px; - padding: 0 9px; - display: flex; - flex-direction: column; - justify-content: center; - position: absolute; - left: 12px; - bottom: 12px; - - @include light-theme { - background: $color-gray-05; - } - - @include dark-theme { - background: $color-gray-60; - } -} - -.text { - font-family: $inter; -} - -.meta-title { - composes: text; - height: 15px; - line-height: 15px; - font: { - size: 12px; - weight: 500; - } - - @include light-theme { - color: $color-gray-90; - } - - @include dark-theme { - color: $color-gray-05; - } -} - -.meta-author { - composes: text; - height: 14px; - line-height: 14px; - font: { - size: 10px; - weight: normal; - } - - @include light-theme { - color: $color-gray-60; - } - - @include dark-theme { - color: $color-gray-25; - } -} diff --git a/sticker-creator/components/StickerPackPreview.stories.tsx b/sticker-creator/components/StickerPackPreview.stories.tsx deleted file mode 100644 index 93ea912c9b97..000000000000 --- a/sticker-creator/components/StickerPackPreview.stories.tsx +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; - -import { StoryRow } from '../elements/StoryRow'; -import { StickerPackPreview } from './StickerPackPreview'; - -export default { - title: 'Sticker Creator/components', -}; - -export const _StickerPackPreview = (): JSX.Element => { - const image = text('image url', '/fixtures/512x515-thumbs-up-lincoln.webp'); - const title = text('title', 'Sticker pack title'); - const author = text('author', 'Sticker pack author'); - const images = React.useMemo(() => Array(39).fill(image), [image]); - - return ( - - - - ); -}; - -_StickerPackPreview.story = { - name: 'StickerPackPreview', -}; diff --git a/sticker-creator/components/StickerPackPreview.tsx b/sticker-creator/components/StickerPackPreview.tsx deleted file mode 100644 index 85836e0ac7b0..000000000000 --- a/sticker-creator/components/StickerPackPreview.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import * as styles from './StickerPackPreview.scss'; -import { useI18n } from '../util/i18n'; - -export type Props = { - images: Array; - title: string; - author: string; -}; - -export const StickerPackPreview = React.memo(function StickerPackPreviewInner({ - images, - title, - author, -}: Props) { - const i18n = useI18n(); - - return ( -
-
- {i18n('StickerCreator--Preview--title')} -
-
-
- {images.map(src => ( - {src} - ))} -
-
-
-
{title}
-
{author}
-
-
- ); -}); diff --git a/sticker-creator/components/Toaster.stories.tsx b/sticker-creator/components/Toaster.stories.tsx deleted file mode 100644 index 047cb36e0e14..000000000000 --- a/sticker-creator/components/Toaster.stories.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2020 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { debounce, dropRight } from 'lodash'; -import { text as textKnob } from '@storybook/addon-knobs'; - -import { StoryRow } from '../elements/StoryRow'; -import { Toaster } from './Toaster'; - -export default { - title: 'Sticker Creator/components', -}; - -export const _Toaster = (): JSX.Element => { - const inputText = textKnob('Slices', ['error 1', 'error 2'].join('|')); - const initialState = React.useMemo(() => inputText.split('|'), [inputText]); - const [state, setState] = React.useState(initialState); - - // TODO not sure how to fix this - // eslint-disable-next-line react-hooks/exhaustive-deps - const handleDismiss = React.useCallback( - // Debounce is required here since auto-dismiss is asynchronously called - // from multiple rendered instances (multiple themes) - debounce(() => { - setState(dropRight); - }, 10), - [setState] - ); - - return ( - - ({ id, text }))} - onDismiss={handleDismiss} - /> - - ); -}; diff --git a/sticker-creator/components/Toaster.tsx b/sticker-creator/components/Toaster.tsx deleted file mode 100644 index 22afe959c4e5..000000000000 --- a/sticker-creator/components/Toaster.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2020 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { last, noop } from 'lodash'; -import { Toast } from '../elements/Toast'; - -export type Props = React.HTMLAttributes & { - loaf: Array<{ id: number; text: string }>; - onDismiss: () => unknown; -}; - -const DEFAULT_DISMISS = 1e4; - -export const Toaster = React.memo(function ToasterInner({ - loaf, - onDismiss, - className, -}: Props) { - const slice = last(loaf); - - React.useEffect(() => { - if (!slice) { - return noop; - } - - const timer = setTimeout(() => { - onDismiss(); - }, DEFAULT_DISMISS); - - return () => { - clearTimeout(timer); - }; - }, [slice, onDismiss]); - - if (!slice) { - return null; - } - - return ( -
- - {slice.text} - -
- ); -}); diff --git a/sticker-creator/custom.d.ts b/sticker-creator/custom.d.ts deleted file mode 100644 index dced16540be7..000000000000 --- a/sticker-creator/custom.d.ts +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2020 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -declare module '*.scss'; diff --git a/sticker-creator/elements/Button.scss b/sticker-creator/elements/Button.scss deleted file mode 100644 index e4dd33c42d81..000000000000 --- a/sticker-creator/elements/Button.scss +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../mixins'; -@import '../../stylesheets/variables'; - -.base { - border: none; - min-width: 80px; - height: 36px; - padding: 0 25px; - border-radius: 4px; - display: flex; - justify-content: center; - align-items: center; - font-family: $inter; - font-weight: normal; - font-size: 14px; - white-space: nowrap; - - @include light-theme() { - background-color: $color-gray-05; - color: $color-gray-90; - } - - @include dark-theme() { - background-color: $color-gray-75; - color: $color-white; - } - - &:disabled { - opacity: 0.4; - } -} - -.primary { - composes: base; - - @include light-theme() { - background-color: $color-ultramarine; - color: $color-white; - } - - @include dark-theme() { - background-color: $color-ultramarine-light; - color: $color-white; - } -} - -.pill { - composes: base; - height: 28px; - border-radius: 15px; - padding: 0 17px; - - @include light-theme() { - color: $color-gray-90; - border: 1px solid $color-gray-90; - background: transparent; - } - - @include dark-theme() { - color: $color-white; - border: 1px solid $color-white; - background: transparent; - } -} - -.pill-primary { - composes: pill; - - @include light-theme() { - border: none; - background-color: $color-ultramarine; - color: $color-white; - } - - @include dark-theme() { - border: none; - background-color: $color-ultramarine-light; - color: $color-white; - } -} diff --git a/sticker-creator/elements/Button.stories.tsx b/sticker-creator/elements/Button.stories.tsx deleted file mode 100644 index c1d7341cc4f0..000000000000 --- a/sticker-creator/elements/Button.stories.tsx +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { action } from '@storybook/addon-actions'; -import { text } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { Button } from './Button'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _Button = (): JSX.Element => { - const onClick = action('onClick'); - const child = text('text', 'foo bar'); - - return ( - <> - - - - - - - - - - - - - - - - - - - - - - - - - - ); -}; diff --git a/sticker-creator/elements/Button.tsx b/sticker-creator/elements/Button.tsx deleted file mode 100644 index 8abd38482151..000000000000 --- a/sticker-creator/elements/Button.tsx +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import React from 'react'; -import classnames from 'classnames'; - -import * as styles from './Button.scss'; - -export type Props = React.ButtonHTMLAttributes & { - pill?: boolean; - primary?: boolean; -}; - -const getClassName = ({ primary, pill }: Props) => { - if (pill && primary) { - return styles.pillPrimary; - } - - if (pill) { - return styles.pill; - } - - if (primary) { - return styles.primary; - } - - return styles.base; -}; - -export function Button({ - className, - children, - ...otherProps -}: React.PropsWithChildren): JSX.Element { - return ( - - ); -} diff --git a/sticker-creator/elements/ConfirmDialog.scss b/sticker-creator/elements/ConfirmDialog.scss deleted file mode 100644 index 3d067df13454..000000000000 --- a/sticker-creator/elements/ConfirmDialog.scss +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../mixins'; -@import '../../stylesheets/variables'; - -.base { - width: 468px; - height: 138px; - padding: 16px 16px 8px 16px; - display: grid; - flex-direction: column; - grid-template-rows: 33px 1fr 28px; - border-radius: 8px; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08), 0 8px 20px 0 rgba(0, 0, 0, 0.33); - - @include light-theme() { - background: $color-white; - } - - @include dark-theme() { - background: $color-gray-75; - } -} - -.text { - font: { - family: $inter; - size: 14px; - } - margin: 0; - - @include light-theme() { - color: $color-gray-90; - } - - @include dark-theme() { - color: $color-gray-05; - } -} - -.title { - composes: text; - font-weight: 500; - - @include light-theme() { - color: $color-gray-90; - } - - @include dark-theme() { - color: $color-white; - } -} - -.bottom { - display: flex; - flex-direction: row; - justify-content: flex-end; - align-content: flex-end; -} - -.button { - min-width: 64px; - height: 28px; - border-radius: 14px; - background: transparent; - margin-left: 4px; - text-align: center; - - font: { - family: $inter; - weight: 500; - size: 13px; - } - - @include light-theme() { - color: $color-gray-60; - border-color: $color-gray-60; - } - - @include dark-theme() { - color: $color-gray-25; - border-color: $color-gray-25; - } -} - -.button-primary { - composes: button; - - @include light-theme() { - color: $color-white; - border-color: $color-ultramarine; - background: $color-ultramarine; - } - - @include dark-theme() { - color: $color-white; - border-color: $color-ultramarine-light; - background: $color-ultramarine-light; - } -} diff --git a/sticker-creator/elements/ConfirmDialog.stories.tsx b/sticker-creator/elements/ConfirmDialog.stories.tsx deleted file mode 100644 index f282aff6a898..000000000000 --- a/sticker-creator/elements/ConfirmDialog.stories.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; -import { action } from '@storybook/addon-actions'; - -import { StoryRow } from './StoryRow'; -import { ConfirmDialog } from './ConfirmDialog'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _ConfirmDialog = (): JSX.Element => { - const title = text('title', 'Foo bar banana baz?'); - const child = text( - 'text', - 'Yadda yadda yadda yadda yadda yadda foo bar banana baz.' - ); - const confirm = text('confirm', 'Upload'); - const cancel = text('cancel', 'Cancel'); - - return ( - - - {child} - - - ); -}; - -_ConfirmDialog.story = { - name: 'ConfirmDialog', -}; diff --git a/sticker-creator/elements/ConfirmDialog.tsx b/sticker-creator/elements/ConfirmDialog.tsx deleted file mode 100644 index 39c6bcb0b7e0..000000000000 --- a/sticker-creator/elements/ConfirmDialog.tsx +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import * as styles from './ConfirmDialog.scss'; -import { useI18n } from '../util/i18n'; - -export type Props = { - readonly title: string; - readonly children: React.ReactNode; - readonly confirm: string; - readonly onConfirm: () => unknown; - readonly cancel?: string; - readonly onCancel: () => unknown; -}; - -export function ConfirmDialog({ - title, - children, - confirm, - cancel, - onConfirm, - onCancel, -}: Props): JSX.Element { - const i18n = useI18n(); - const cancelText = cancel || i18n('StickerCreator--ConfirmDialog--cancel'); - - return ( -
-

{title}

-

{children}

-
- - -
-
- ); -} diff --git a/sticker-creator/elements/CopyText.scss b/sticker-creator/elements/CopyText.scss deleted file mode 100644 index 2483f6af6d69..000000000000 --- a/sticker-creator/elements/CopyText.scss +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; -@import '../mixins'; - -.container { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - width: 330px; - height: 36px; -} - -.input { - width: 242px; - height: 36px; - line-height: 34px; - padding: 0 12px; - border-radius: 4px; - background-color: transparent; - font-size: 14px; - font-family: $inter; - - &::placeholder { - color: $color-gray-45; - } - - @include light-theme() { - border: 1px solid $color-gray-15; - color: $color-gray-90; - } - - @include dark-theme() { - border: 1px solid $color-gray-60; - color: $color-white; - } -} diff --git a/sticker-creator/elements/CopyText.stories.tsx b/sticker-creator/elements/CopyText.stories.tsx deleted file mode 100644 index 5b819bd96162..000000000000 --- a/sticker-creator/elements/CopyText.stories.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { CopyText } from './CopyText'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _CopyText = (): JSX.Element => { - const label = text('label', 'foo bar'); - const value = text('value', 'foo bar'); - - return ( - - - - ); -}; - -_CopyText.story = { - name: 'CopyText', -}; diff --git a/sticker-creator/elements/CopyText.tsx b/sticker-creator/elements/CopyText.tsx deleted file mode 100644 index 855bb3105ff8..000000000000 --- a/sticker-creator/elements/CopyText.tsx +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import copy from 'copy-text-to-clipboard'; -import * as styles from './CopyText.scss'; -import { Button } from './Button'; -import { useI18n } from '../util/i18n'; - -export type Props = { - value: string; - label: string; - onCopy?: () => unknown; -}; - -export const CopyText: React.ComponentType = React.memo( - function CopyTextInner({ label, onCopy, value }) { - const i18n = useI18n(); - const handleClick = React.useCallback(() => { - copy(value); - if (onCopy) { - onCopy(); - } - }, [onCopy, value]); - - return ( -
- - -
- ); - } -); diff --git a/sticker-creator/elements/DropZone.scss b/sticker-creator/elements/DropZone.scss deleted file mode 100644 index 08a0016baabe..000000000000 --- a/sticker-creator/elements/DropZone.scss +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; -@import '../mixins'; - -.base { - width: 100%; - height: 100%; - display: flex; - justify-content: center; - align-items: center; - flex-direction: column; - flex-grow: 1; - - @include light-theme() { - color: $color-gray-60; - } - - @include dark-theme() { - color: $color-gray-45; - } -} - -.text { - margin: 16px 0 0 0; - font-family: $inter; - font-size: 14px; - font-weight: normal; - - @include light-theme() { - color: $color-gray-60; - } - - @include dark-theme() { - color: $color-gray-45; - } -} - -.standalone { - composes: base; - border-radius: 4px; - border: 2px solid; - - @include light-theme() { - border-color: $color-gray-25; - } - - @include dark-theme() { - border-color: $color-gray-60; - } -} - -.active { - composes: standalone; - - @include light-theme() { - border-color: $color-ultramarine; - } - - @include dark-theme() { - border-color: $color-ultramarine-light; - } -} diff --git a/sticker-creator/elements/DropZone.stories.tsx b/sticker-creator/elements/DropZone.stories.tsx deleted file mode 100644 index 5c8637b78157..000000000000 --- a/sticker-creator/elements/DropZone.stories.tsx +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { action } from '@storybook/addon-actions'; - -import { DropZone } from './DropZone'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _DropZone = (): JSX.Element => { - return ; -}; - -_DropZone.story = { - name: 'DropZone', -}; diff --git a/sticker-creator/elements/DropZone.tsx b/sticker-creator/elements/DropZone.tsx deleted file mode 100644 index 9cd286444304..000000000000 --- a/sticker-creator/elements/DropZone.tsx +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import type { FileWithPath } from 'react-dropzone'; - -import * as styles from './DropZone.scss'; -import { useI18n } from '../util/i18n'; -import { useStickerDropzone } from '../util/useStickerDropzone'; -import { isNotNil } from '../../ts/util/isNotNil'; - -export type Props = { - readonly inner?: boolean; - readonly label: string; - onDrop(files: Array): unknown; - onDragActive?(active: boolean): unknown; -}; - -const getClassName = ({ inner }: Props, isDragActive: boolean) => { - if (inner) { - return styles.base; - } - - if (isDragActive) { - return styles.active; - } - - return styles.standalone; -}; - -export function DropZone(props: Props): JSX.Element { - const { inner, label, onDrop, onDragActive } = props; - const i18n = useI18n(); - - const handleDrop = React.useCallback( - (files: ReadonlyArray) => { - onDrop(files.map(({ path }) => path).filter(isNotNil)); - }, - [onDrop] - ); - - const { getRootProps, getInputProps, isDragActive } = - useStickerDropzone(handleDrop); - - React.useEffect(() => { - if (onDragActive) { - onDragActive(isDragActive); - } - }, [isDragActive, onDragActive]); - - return ( -
- - - - - {!inner ? ( -

- {isDragActive - ? i18n('StickerCreator--DropZone--activeText') - : i18n('StickerCreator--DropZone--staticText')} -

- ) : null} -
- ); -} diff --git a/sticker-creator/elements/LabeledCheckbox.scss b/sticker-creator/elements/LabeledCheckbox.scss deleted file mode 100644 index 99c75af325d2..000000000000 --- a/sticker-creator/elements/LabeledCheckbox.scss +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; -@import '../mixins'; - -.base { - display: flex; - flex-direction: row; - align-items: center; - - padding: 2px; - - // We'd really like to use focus-within-visible or :has(:focus-visible), to ensure that - // this doesn't show when using the mouse, but neither are ready yet! - &:focus-within { - outline: 2px solid -webkit-focus-ring-color; - } -} - -.input { - position: absolute; - width: 0; - height: 0; - opacity: 0; -} - -.checkbox { - width: 18px; - height: 18px; - border-radius: 2px; - display: flex; - justify-content: center; - align-items: center; - border: { - width: 2px; - style: solid; - } - - @include light-theme() { - border-color: $color-gray-60; - } - - @include dark-theme() { - border-color: $color-gray-25; - } -} - -.checkbox-checked { - composes: checkbox; - border: none; - background-color: $color-ultramarine; - color: $color-white; -} - -.label { - margin-left: 6px; - position: relative; - user-select: none; -} diff --git a/sticker-creator/elements/LabeledCheckbox.stories.tsx b/sticker-creator/elements/LabeledCheckbox.stories.tsx deleted file mode 100644 index 008af57e5354..000000000000 --- a/sticker-creator/elements/LabeledCheckbox.stories.tsx +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { LabeledCheckbox } from './LabeledCheckbox'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _LabeledCheckbox = (): JSX.Element => { - const child = text('label', 'foo bar'); - const [checked, setChecked] = React.useState(false); - - return ( - - - {child} - - - ); -}; diff --git a/sticker-creator/elements/LabeledCheckbox.tsx b/sticker-creator/elements/LabeledCheckbox.tsx deleted file mode 100644 index c388c81e6658..000000000000 --- a/sticker-creator/elements/LabeledCheckbox.tsx +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import * as styles from './LabeledCheckbox.scss'; -import { Inline } from './Typography'; - -export type Props = { - children: React.ReactNode; - value?: boolean; - onChange?: (value: boolean) => unknown; -}; - -const checkSvg = ( - - - -); - -export const LabeledCheckbox = React.memo(function LabeledCheckboxInner({ - children, - value, - onChange, -}: Props) { - const handleChange = React.useCallback(() => { - if (onChange !== undefined) { - onChange(!value); - } - }, [onChange, value]); - - const className = value ? styles.checkboxChecked : styles.checkbox; - - return ( - - ); -}); diff --git a/sticker-creator/elements/LabeledInput.scss b/sticker-creator/elements/LabeledInput.scss deleted file mode 100644 index a803bf90a754..000000000000 --- a/sticker-creator/elements/LabeledInput.scss +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; -@import '../mixins'; - -.container { - display: flex; - flex-direction: column; - align-items: flex-start; - justify-content: space-between; - height: 56px; -} - -.label { - user-select: none; - font-size: 13px; - font-family: $inter; - font-weight: 500; -} - -.input { - width: 448px; - height: 34px; - line-height: 34px; - padding: 0 12px; - border-radius: 4px; - background-color: transparent; - font-size: 14px; - font-family: $inter; - - &::placeholder { - color: $color-gray-45; - } - - @include light-theme() { - border: 1px solid $color-gray-15; - color: $color-gray-90; - } - - @include dark-theme() { - border: 1px solid $color-gray-60; - color: $color-white; - } - - &:focus { - outline: none; - padding: 0 11px; - - @include light-theme() { - border: 2px solid $color-ultramarine; - } - - @include dark-theme() { - border: 2px solid $color-ultramarine-light; - } - } -} diff --git a/sticker-creator/elements/LabeledInput.stories.tsx b/sticker-creator/elements/LabeledInput.stories.tsx deleted file mode 100644 index 4403744c5126..000000000000 --- a/sticker-creator/elements/LabeledInput.stories.tsx +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { LabeledInput } from './LabeledInput'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _LabeledInput = (): JSX.Element => { - const child = text('label', 'foo bar'); - const placeholder = text('placeholder', 'foo bar'); - const [value, setValue] = React.useState(''); - - return ( - - - {child} - - - ); -}; - -_LabeledInput.story = { - name: 'LabeledInput', -}; diff --git a/sticker-creator/elements/LabeledInput.tsx b/sticker-creator/elements/LabeledInput.tsx deleted file mode 100644 index cc89bc6af026..000000000000 --- a/sticker-creator/elements/LabeledInput.tsx +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import * as styles from './LabeledInput.scss'; -import { Inline } from './Typography'; - -export type Props = { - children: React.ReactNode; - placeholder?: string; - value?: string; - onChange?: (value: string) => unknown; -}; - -export const LabeledInput = React.memo(function LabeledInputInner({ - children, - value, - placeholder, - onChange, -}: Props) { - const handleChange = React.useCallback( - (e: React.ChangeEvent) => { - if (onChange !== undefined) { - onChange(e.currentTarget.value); - } - }, - [onChange] - ); - - return ( - - ); -}); diff --git a/sticker-creator/elements/MessageBubble.scss b/sticker-creator/elements/MessageBubble.scss deleted file mode 100644 index 08bbd31d2070..000000000000 --- a/sticker-creator/elements/MessageBubble.scss +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; - -.base { - background-color: $color-ultramarine; - padding: 6px 12px; - border-radius: 18px; - color: $color-white-alpha-90; - font: { - size: 12px; - family: $inter; - weight: normal; - } -} diff --git a/sticker-creator/elements/MessageBubble.stories.tsx b/sticker-creator/elements/MessageBubble.stories.tsx deleted file mode 100644 index c952cb8251a7..000000000000 --- a/sticker-creator/elements/MessageBubble.stories.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { number, text } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { MessageBubble } from './MessageBubble'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _MessageBubble = (): JSX.Element => { - const child = text('text', 'Foo bar banana baz'); - const minutesAgo = number('minutesAgo', 3); - - return ( - - {child} - - ); -}; - -_MessageBubble.story = { - name: 'MessageBubble', -}; diff --git a/sticker-creator/elements/MessageBubble.tsx b/sticker-creator/elements/MessageBubble.tsx deleted file mode 100644 index b146d621ff0d..000000000000 --- a/sticker-creator/elements/MessageBubble.tsx +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import * as styles from './MessageBubble.scss'; -import type { Props as MessageMetaProps } from './MessageMeta'; -import { MessageMeta } from './MessageMeta'; - -export type Props = Pick & { - children: React.ReactNode; -}; - -export function MessageBubble({ children, minutesAgo }: Props): JSX.Element { - return ( -
- {children} - -
- ); -} diff --git a/sticker-creator/elements/MessageMeta.scss b/sticker-creator/elements/MessageMeta.scss deleted file mode 100644 index 291f16c522a0..000000000000 --- a/sticker-creator/elements/MessageMeta.scss +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../mixins'; -@import '../../stylesheets/variables'; - -.base { - display: flex; - flex-direction: row; - justify-content: flex-end; - margin-top: 3px; -} - -.item { - margin-left: 6px; - font: { - size: 11px; - family: $inter; - weight: normal; - } -} - -.bubble { - composes: item; - color: rgba(255, 255, 255, 0.8); -} - -.light { - composes: item; - color: $color-gray-60; -} - -.dark { - composes: item; - color: rgba(255, 255, 255, 0.8); -} diff --git a/sticker-creator/elements/MessageMeta.tsx b/sticker-creator/elements/MessageMeta.tsx deleted file mode 100644 index b96731cba1e3..000000000000 --- a/sticker-creator/elements/MessageMeta.tsx +++ /dev/null @@ -1,59 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import * as styles from './MessageMeta.scss'; -import { useI18n } from '../util/i18n'; - -export type Props = { - kind?: 'bubble' | 'dark' | 'light'; - minutesAgo: number; -}; - -const getItemClass = ({ kind }: Props) => { - if (kind === 'dark') { - return styles.dark; - } - - if (kind === 'light') { - return styles.light; - } - - return styles.bubble; -}; - -export const MessageMeta = React.memo(function MessageMetaInner(props: Props) { - const i18n = useI18n(); - const itemClass = getItemClass(props); - - return ( -
- - - - - - -
- {i18n('minutesAgo', [props.minutesAgo.toString()])} -
- - - - - - - - - - - - - - -
- ); -}); diff --git a/sticker-creator/elements/MessageSticker.scss b/sticker-creator/elements/MessageSticker.scss deleted file mode 100644 index 65edeccbe696..000000000000 --- a/sticker-creator/elements/MessageSticker.scss +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; - -.base { - padding: 6px 12px; -} - -.image { - width: 116px; - height: 116px; -} diff --git a/sticker-creator/elements/MessageSticker.stories.tsx b/sticker-creator/elements/MessageSticker.stories.tsx deleted file mode 100644 index 2e8538a402fd..000000000000 --- a/sticker-creator/elements/MessageSticker.stories.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { number, text } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { MessageSticker } from './MessageSticker'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _MessageSticker = (): JSX.Element => { - const image = text('image url', '/fixtures/512x515-thumbs-up-lincoln.webp'); - const minutesAgo = number('minutesAgo', 3); - - return ( - - - - ); -}; - -_MessageSticker.story = { - name: 'MessageSticker', -}; diff --git a/sticker-creator/elements/MessageSticker.tsx b/sticker-creator/elements/MessageSticker.tsx deleted file mode 100644 index e35022778224..000000000000 --- a/sticker-creator/elements/MessageSticker.tsx +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import * as styles from './MessageSticker.scss'; -import type { Props as MessageMetaProps } from './MessageMeta'; -import { MessageMeta } from './MessageMeta'; - -export type Props = MessageMetaProps & { - image: string; -}; - -export function MessageSticker({ - image, - kind, - minutesAgo, -}: Props): JSX.Element { - return ( -
- Sticker - -
- ); -} diff --git a/sticker-creator/elements/PageHeader.scss b/sticker-creator/elements/PageHeader.scss deleted file mode 100644 index 6ed2d2749be1..000000000000 --- a/sticker-creator/elements/PageHeader.scss +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; -@import '../mixins'; - -.base { - height: 47px; - width: 100%; - border-bottom-width: 1px; - border-bottom-style: solid; - padding: 0 16px; - display: flex; - flex-direction: row; - align-items: center; - flex-shrink: 0; - - @include light-theme() { - border-bottom-color: $color-gray-15; - } - - @include dark-theme() { - border-bottom-color: $color-gray-75; - } -} diff --git a/sticker-creator/elements/PageHeader.stories.tsx b/sticker-creator/elements/PageHeader.stories.tsx deleted file mode 100644 index de7143eeb039..000000000000 --- a/sticker-creator/elements/PageHeader.stories.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { PageHeader } from './PageHeader'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _PageHeader = (): JSX.Element => { - const child = text('text', 'foo bar'); - - return ( - - {child} - - ); -}; - -_PageHeader.story = { - name: 'PageHeader', -}; diff --git a/sticker-creator/elements/PageHeader.tsx b/sticker-creator/elements/PageHeader.tsx deleted file mode 100644 index 6f595a8c4afb..000000000000 --- a/sticker-creator/elements/PageHeader.tsx +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import * as styles from './PageHeader.scss'; -import { H1 } from './Typography'; - -export type Props = { - children: React.ReactNode; -}; - -export const PageHeader = React.memo(function PageHeaderInner({ - children, -}: Props) { - return

{children}

; -}); diff --git a/sticker-creator/elements/ProgressBar.scss b/sticker-creator/elements/ProgressBar.scss deleted file mode 100644 index 0a73e843dc0a..000000000000 --- a/sticker-creator/elements/ProgressBar.scss +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; -@import '../mixins'; - -.base { - height: 4px; - width: 100%; - max-width: 448px; - - @include light-theme() { - background: $color-gray-15; - } - - @include dark-theme() { - background: $color-gray-75; - } -} - -.bar { - height: 4px; - width: 0px; - background: $color-ultramarine; - - transition: width 100ms ease-out; -} diff --git a/sticker-creator/elements/ProgressBar.stories.tsx b/sticker-creator/elements/ProgressBar.stories.tsx deleted file mode 100644 index 6e4401576690..000000000000 --- a/sticker-creator/elements/ProgressBar.stories.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { number } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { ProgressBar } from './ProgressBar'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _ProgressBar = (): JSX.Element => { - const count = number('count', 5); - const total = number('total', 10); - - return ( - - - - ); -}; - -_ProgressBar.story = { - name: 'ProgressBar', -}; diff --git a/sticker-creator/elements/ProgressBar.tsx b/sticker-creator/elements/ProgressBar.tsx deleted file mode 100644 index ec783a82bd7f..000000000000 --- a/sticker-creator/elements/ProgressBar.tsx +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import classnames from 'classnames'; - -import * as styles from './ProgressBar.scss'; - -export type Props = Pick, 'className'> & { - readonly count: number; - readonly total: number; -}; - -export const ProgressBar = React.memo(function ProgressBarInner({ - className, - count, - total, -}: Props) { - return ( -
-
-
- ); -}); diff --git a/sticker-creator/elements/StickerPreview.scss b/sticker-creator/elements/StickerPreview.scss deleted file mode 100644 index 9d623e24b9f4..000000000000 --- a/sticker-creator/elements/StickerPreview.scss +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../mixins'; -@import '../../stylesheets/variables'; - -.base { - width: 380px; - padding: 4px; - display: flex; - flex-direction: row; - border-radius: 8px; - box-shadow: 0 2px 13px 3px rgba(0, 0, 0, 0.3); - position: relative; - - @include light-theme() { - background: $color-white; - } - - @include dark-theme() { - background: $color-gray-75; - } -} - -.frame { - width: 50%; - padding: 12px 12px 3px 12px; -} - -.frame-light { - composes: frame; - background: $color-white; - border-radius: 6px 0 0 6px; -} - -.frame-dark { - composes: frame; - background: $color-black; - border-radius: 0 6px 6px 0; -} - -.arrow { - position: absolute; - width: 0; - height: 0; - border-style: solid; -} - -.arrow-top { - composes: arrow; - border-width: 0 8px 8px 8px; - top: -8px; - - @include light-theme() { - border-color: transparent transparent $color-white transparent; - } - - @include dark-theme() { - border-color: transparent transparent $color-gray-75 transparent; - } -} - -.arrow-bottom { - composes: arrow; - border-width: 8px 8px 0 8px; - bottom: -8px; - - @include light-theme() { - border-color: $color-white transparent transparent transparent; - } - - @include dark-theme() { - border-color: $color-gray-75 transparent transparent transparent; - } -} - -.arrow-left { - composes: arrow; - border-width: 8px 8px 8px 0; - left: -8px; - - @include light-theme() { - border-color: transparent $color-white transparent transparent; - } - - @include dark-theme() { - border-color: transparent $color-gray-75 transparent transparent; - } -} - -.arrow-right { - composes: arrow; - border-width: 8px 0 8px 8px; - right: -8px; - - @include light-theme() { - border-color: transparent transparent transparent $color-white; - } - - @include dark-theme() { - border-color: transparent transparent transparent $color-gray-75; - } -} diff --git a/sticker-creator/elements/StickerPreview.stories.tsx b/sticker-creator/elements/StickerPreview.stories.tsx deleted file mode 100644 index b44c9f25f2ce..000000000000 --- a/sticker-creator/elements/StickerPreview.stories.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { StickerPreview } from './StickerPreview'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _StickerPreview = (): JSX.Element => { - const image = text('image url', '/fixtures/512x515-thumbs-up-lincoln.webp'); - - return ( - - - - ); -}; - -_StickerPreview.story = { - name: 'StickerPreview', -}; diff --git a/sticker-creator/elements/StickerPreview.tsx b/sticker-creator/elements/StickerPreview.tsx deleted file mode 100644 index f275bb2a1c20..000000000000 --- a/sticker-creator/elements/StickerPreview.tsx +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import type { PopperArrowProps } from 'react-popper'; -import type { Placement } from '@popperjs/core'; -import * as styles from './StickerPreview.scss'; -import { MessageBubble } from './MessageBubble'; -import type { Props as MessageStickerProps } from './MessageSticker'; -import { MessageSticker } from './MessageSticker'; -import { useI18n } from '../util/i18n'; - -export type Props = Pick, 'style'> & { - image: string; - arrowProps?: PopperArrowProps; - placement?: Placement; -}; - -const renderMessages = ( - text: string, - image: string, - kind: MessageStickerProps['kind'] -) => ( - <> - {text} - - -); - -const getArrowClass = (placement?: Placement) => { - if (placement === 'top') { - return styles.arrowBottom; - } - - if (placement === 'right') { - return styles.arrowLeft; - } - - if (placement === 'left') { - return styles.arrowRight; - } - - return styles.arrowTop; -}; - -export const StickerPreview = React.memo( - React.forwardRef( - ({ image, style, arrowProps, placement }: Props, ref) => { - const i18n = useI18n(); - - return ( -
- {arrowProps ? ( -
- ) : null} -
- {renderMessages( - i18n('StickerCreator--StickerPreview--light'), - image, - 'light' - )} -
-
- {renderMessages( - i18n('StickerCreator--StickerPreview--dark'), - image, - 'dark' - )} -
-
- ); - } - ) -); diff --git a/sticker-creator/elements/StoryRow.scss b/sticker-creator/elements/StoryRow.scss deleted file mode 100644 index f26214ae5a2c..000000000000 --- a/sticker-creator/elements/StoryRow.scss +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -.base { - flex: 1; - display: flex; - flex-direction: row; - justify-content: center; - align-items: center; - width: 100%; -} - -.left { - composes: base; - justify-content: flex-start; -} - -.right { - composes: base; - justify-content: flex-end; -} - -.top { - composes: base; - align-items: flex-start; -} - -.bottom { - composes: base; - align-items: flex-end; -} diff --git a/sticker-creator/elements/StoryRow.tsx b/sticker-creator/elements/StoryRow.tsx deleted file mode 100644 index 342f8795e2fa..000000000000 --- a/sticker-creator/elements/StoryRow.tsx +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import * as styles from './StoryRow.scss'; - -type Props = { - left?: boolean; - right?: boolean; - top?: boolean; - bottom?: boolean; -}; - -const getClassName = ({ left, right, top, bottom }: Props) => { - if (left) { - return styles.left; - } - - if (right) { - return styles.right; - } - - if (top) { - return styles.top; - } - - if (bottom) { - return styles.bottom; - } - - return styles.base; -}; - -export function StoryRow({ - children, - ...props -}: React.PropsWithChildren): JSX.Element { - return
{children}
; -} diff --git a/sticker-creator/elements/Toast.scss b/sticker-creator/elements/Toast.scss deleted file mode 100644 index 65e9c6891dae..000000000000 --- a/sticker-creator/elements/Toast.scss +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; - -.base { - padding: 8px 12px; - border-radius: 4px; - border: none; - background-color: $color-gray-75; - box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.08), 0 8px 20px 0px rgba(0, 0, 0, 0.33); - font-family: $inter; - font-weight: normal; - font-size: 14px; - color: $color-gray-05; - line-height: 18px; - cursor: pointer; -} diff --git a/sticker-creator/elements/Toast.stories.tsx b/sticker-creator/elements/Toast.stories.tsx deleted file mode 100644 index 2d6b98c07af2..000000000000 --- a/sticker-creator/elements/Toast.stories.tsx +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; -import { action } from '@storybook/addon-actions'; - -import { StoryRow } from './StoryRow'; -import { Toast } from './Toast'; - -export default { - title: 'Sticker Creator/elements', -}; - -export const _Toast = (): JSX.Element => { - const child = text('text', 'foo bar'); - - return ( - - {child} - - ); -}; diff --git a/sticker-creator/elements/Toast.tsx b/sticker-creator/elements/Toast.tsx deleted file mode 100644 index 864ab5262c88..000000000000 --- a/sticker-creator/elements/Toast.tsx +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import classNames from 'classnames'; -import * as styles from './Toast.scss'; - -export type Props = React.HTMLAttributes & { - children: React.ReactNode; -}; - -export const Toast = React.memo(function ToastInner({ - children, - className, - ...rest -}: Props) { - return ( - - ); -}); diff --git a/sticker-creator/elements/Typography.scss b/sticker-creator/elements/Typography.scss deleted file mode 100644 index 19edf2e80a28..000000000000 --- a/sticker-creator/elements/Typography.scss +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -@import '../../stylesheets/variables'; -@import '../mixins'; - -.base { - font-family: $inter; - margin: 0; -} - -.heading { - composes: base; - font-weight: 500; -} - -.h1 { - composes: heading; - font-size: 16px; - line-height: 20px; - - @include light-theme() { - color: $color-gray-90; - } - - @include dark-theme() { - color: $color-gray-05; - } -} - -.h2 { - composes: heading; - font-size: 14px; - line-height: 18px; - margin-bottom: 8px; - - @include light-theme() { - color: $color-gray-90; - } - - @include dark-theme() { - color: $color-white; - } -} - -.text { - composes: base; - font-size: 13px; - line-height: 18px; - - @include light-theme() { - color: $color-gray-90; - } - - @include dark-theme() { - color: $color-white; - } - - a { - color: $color-ultramarine; - text-decoration: none; - } -} - -.text-center { - composes: text; - text-align: center; -} - -.secondary { - @include light-theme() { - color: $color-gray-60; - } - - @include dark-theme() { - color: $color-gray-25; - } -} diff --git a/sticker-creator/elements/Typography.stories.tsx b/sticker-creator/elements/Typography.stories.tsx deleted file mode 100644 index 6319e81e4ee2..000000000000 --- a/sticker-creator/elements/Typography.stories.tsx +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -/* eslint-disable jsx-a11y/anchor-is-valid */ - -import * as React from 'react'; -import { text } from '@storybook/addon-knobs'; - -import { StoryRow } from './StoryRow'; -import { H1, H2, Text } from './Typography'; - -export default { - title: 'Sticker Creator/elements', -}; - -export function Typography(): JSX.Element { - const child = text('text', 'foo bar'); - - return ( - <> - -

{child}

-
- -

{child}

-
- - - {child} {child} {child} {child} - - - - - {child} {child} {child} {child}{' '} - Something something something dark side. - - - - ); -} diff --git a/sticker-creator/elements/Typography.tsx b/sticker-creator/elements/Typography.tsx deleted file mode 100644 index 80fe1fecb135..000000000000 --- a/sticker-creator/elements/Typography.tsx +++ /dev/null @@ -1,76 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import classnames from 'classnames'; - -import * as styles from './Typography.scss'; - -export type Props = { - children: React.ReactNode; -}; - -export type HeadingProps = React.HTMLAttributes; -export type ParagraphProps = React.HTMLAttributes & { - center?: boolean; - wide?: boolean; - secondary?: boolean; -}; -export type SpanProps = React.HTMLAttributes; - -export const H1 = React.memo(function H1Inner({ - children, - className, - ...rest -}: Props & HeadingProps) { - return ( -

- {children} -

- ); -}); - -export const H2 = React.memo(function H2Inner({ - children, - className, - ...rest -}: Props & HeadingProps) { - return ( -

- {children} -

- ); -}); - -export const Text = React.memo(function TextInner({ - children, - className, - center, - secondary, - ...rest -}: Props & ParagraphProps) { - return ( -

- {children} -

- ); -}); - -export const Inline = React.memo(function InlineInner({ - children, - className, - ...rest -}: Props & SpanProps) { - return ( - - {children} - - ); -}); diff --git a/sticker-creator/elements/icons/AddEmoji.tsx b/sticker-creator/elements/icons/AddEmoji.tsx deleted file mode 100644 index 7074f07e10e3..000000000000 --- a/sticker-creator/elements/icons/AddEmoji.tsx +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; - -export const AddEmoji = React.memo(function AddEmojiInner() { - return ( - - - - ); -}); diff --git a/sticker-creator/elements/icons/index.tsx b/sticker-creator/elements/icons/index.tsx deleted file mode 100644 index aacea4a8d882..000000000000 --- a/sticker-creator/elements/icons/index.tsx +++ /dev/null @@ -1,4 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -export { AddEmoji } from './AddEmoji'; diff --git a/sticker-creator/index.html b/sticker-creator/index.html deleted file mode 100644 index b5aeb8c25463..000000000000 --- a/sticker-creator/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - -
- - - diff --git a/sticker-creator/index.tsx b/sticker-creator/index.tsx deleted file mode 100644 index 52b1ef137cb0..000000000000 --- a/sticker-creator/index.tsx +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import { render } from 'react-dom'; -import { Root } from './root'; - -const root = document.getElementById('root'); - -// eslint-disable-next-line no-console -console.log('Sticker Creator: Starting root'); -render(, root); diff --git a/sticker-creator/preload.ts b/sticker-creator/preload.ts deleted file mode 100644 index d71d7de2b26e..000000000000 --- a/sticker-creator/preload.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import './window/phase1-dependencies'; -import './window/phase2-signal'; -import './window/phase3-sticker-functions'; -import './window/phase4-theme'; - -import { SignalContext } from '../ts/windows/context'; - -SignalContext.log.info('sticker-creator preload complete...'); diff --git a/sticker-creator/root.tsx b/sticker-creator/root.tsx deleted file mode 100644 index 5cb7118d9f35..000000000000 --- a/sticker-creator/root.tsx +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import { hot } from 'react-hot-loader/root'; -import * as React from 'react'; -import { Provider as ReduxProvider } from 'react-redux'; -import { Router } from 'react-router-dom'; -import { App } from './app'; -import { history } from './util/history'; -import { store } from './store'; -import { I18n } from './util/i18n'; - -const { localeMessages, SignalContext } = window; - -function ColdRoot() { - return ( - - - - - - - - ); -} - -export const Root = hot(ColdRoot); diff --git a/sticker-creator/store/ducks/stickers.ts b/sticker-creator/store/ducks/stickers.ts deleted file mode 100644 index b01e020a00cd..000000000000 --- a/sticker-creator/store/ducks/stickers.ts +++ /dev/null @@ -1,332 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -/* eslint-disable no-param-reassign */ - -import { useMemo } from 'react'; -import type { Draft } from 'redux-ts-utils'; -import { createAction, handleAction, reduceReducers } from 'redux-ts-utils'; -import { useDispatch, useSelector } from 'react-redux'; -import { createSelector } from 'reselect'; -import { clamp, find, isString, pull, remove, take, uniq } from 'lodash'; -import type { SortEnd } from 'react-sortable-hoc'; -import { bindActionCreators } from 'redux'; -import arrayMove from 'array-move'; -import type { AppState } from '../reducer'; -import type { - PackMetaData, - StickerImageData, - StickerData, -} from '../../util/preload'; -import type { EmojiPickDataType } from '../../../ts/components/emoji/EmojiPicker'; -import { convertShortName } from '../../../ts/components/emoji/lib'; -import { isNotNil } from '../../../ts/util/isNotNil'; - -type StickerEmojiData = { id: string; emoji: EmojiPickDataType }; - -export const initializeStickers = createAction>( - 'stickers/initializeStickers' -); -export const addImageData = createAction( - 'stickers/addSticker' -); -export const removeSticker = createAction('stickers/removeSticker'); -export const moveSticker = createAction('stickers/moveSticker'); -export const setCover = createAction('stickers/setCover'); -export const resetCover = createAction('stickers/resetCover'); -export const setEmoji = createAction('stickers/setEmoji'); -export const setTitle = createAction('stickers/setTitle'); -export const setAuthor = createAction('stickers/setAuthor'); -export const setPackMeta = createAction('stickers/setPackMeta'); - -export const addToast = createAction<{ - key: string; - subs?: Record; -}>('stickers/addToast'); -export const dismissToast = createAction('stickers/dismissToast'); - -export const resetStatus = createAction('stickers/resetStatus'); -export const reset = createAction('stickers/reset'); - -export const minStickers = 1; -export const maxStickers = 200; -export const maxByteSize = 300 * 1024; - -type StateStickerData = { - readonly imageData?: StickerImageData; - readonly emoji?: EmojiPickDataType; -}; - -type StateToastData = { - key: string; - subs?: Record; -}; - -export type State = { - readonly order: Array; - readonly cover?: StickerImageData; - readonly title: string; - readonly author: string; - readonly packId: string; - readonly packKey: string; - readonly toasts: Array; - readonly data: { - readonly [src: string]: StateStickerData; - }; -}; - -export type Actions = { - addImageData: typeof addImageData; - initializeStickers: typeof initializeStickers; - removeSticker: typeof removeSticker; - moveSticker: typeof moveSticker; - setCover: typeof setCover; - setEmoji: typeof setEmoji; - setTitle: typeof setTitle; - setAuthor: typeof setAuthor; - setPackMeta: typeof setPackMeta; - addToast: typeof addToast; - dismissToast: typeof dismissToast; - reset: typeof reset; - resetStatus: typeof resetStatus; -}; - -const defaultState: State = { - order: [], - data: {}, - title: '', - author: '', - packId: '', - packKey: '', - toasts: [], -}; - -const adjustCover = (state: Draft) => { - const first = state.order[0]; - - if (first) { - state.cover = state.data[first].imageData; - } else { - delete state.cover; - } -}; - -export const reducer = reduceReducers( - [ - handleAction(initializeStickers, (state, { payload }) => { - const truncated = take( - uniq([...state.order, ...payload]), - maxStickers - state.order.length - ); - truncated.forEach(path => { - if (!state.data[path]) { - state.data[path] = {}; - state.order.push(path); - } - }); - }), - - handleAction(addImageData, (state, { payload }) => { - if (payload.buffer.byteLength > maxByteSize) { - state.toasts.push({ key: 'StickerCreator--Toasts--tooLarge' }); - pull(state.order, payload.path); - delete state.data[payload.path]; - } else { - const data = state.data[payload.path]; - - // If we are adding image data, proceed to update the state and add/update a toast - if (data && !data.imageData) { - data.imageData = payload; - - const key = 'icu:StickerCreator--Toasts--imagesAdded'; - - const toast = (() => { - const oldToast = find(state.toasts, { key }); - - if (oldToast) { - return oldToast; - } - - const newToast = { key, subs: { count: '0' } }; - state.toasts.push(newToast); - - return newToast; - })(); - - const previousSub = toast?.subs?.count; - if (toast && isString(previousSub)) { - const previousCount = parseInt(previousSub, 10); - const newCount = Number.isFinite(previousCount) - ? previousCount + 1 - : 1; - - toast.subs = toast.subs || {}; - toast.subs.count = newCount.toString(); - } - } - } - - adjustCover(state); - }), - - handleAction(removeSticker, (state, { payload }) => { - pull(state.order, payload); - delete state.data[payload]; - adjustCover(state); - }), - - handleAction(moveSticker, (state, { payload }) => { - arrayMove.mutate(state.order, payload.oldIndex, payload.newIndex); - }), - - handleAction(setCover, (state, { payload }) => { - state.cover = payload; - }), - - handleAction(resetCover, state => { - adjustCover(state); - }), - - handleAction(setEmoji, (state, { payload }) => { - const data = state.data[payload.id]; - if (data) { - data.emoji = payload.emoji; - } - }), - - handleAction(setTitle, (state, { payload }) => { - state.title = payload; - }), - - handleAction(setAuthor, (state, { payload }) => { - state.author = payload; - }), - - handleAction(setPackMeta, (state, { payload: { packId, key } }) => { - state.packId = packId; - state.packKey = key; - }), - - handleAction(addToast, (state, { payload: toast }) => { - remove(state.toasts, { key: toast.key }); - state.toasts.push(toast); - }), - - handleAction(dismissToast, state => { - state.toasts.pop(); - }), - - handleAction(resetStatus, state => { - state.toasts = []; - }), - - handleAction(reset, () => defaultState), - ], - defaultState -); - -export const useTitle = (): string => - useSelector(({ stickers }: AppState) => stickers.title); - -export const useAuthor = (): string => - useSelector(({ stickers }: AppState) => stickers.author); - -export const useCover = (): StickerImageData | undefined => - useSelector(({ stickers }: AppState) => stickers.cover); - -export const useStickerOrder = (): Array => - useSelector(({ stickers }: AppState) => stickers.order); - -export const useStickerData = (src: string): StateStickerData => - useSelector(({ stickers }: AppState) => stickers.data[src]); - -export const useStickersReady = (): boolean => - useSelector( - ({ stickers }: AppState) => - stickers.order.length >= minStickers && - stickers.order.length <= maxStickers && - Object.values(stickers.data).every(({ imageData }) => Boolean(imageData)) - ); - -export const useEmojisReady = (): boolean => - useSelector(({ stickers }: AppState) => - Object.values(stickers.data).every(({ emoji }) => !!emoji) - ); - -export const useAllDataValid = (): boolean => { - const stickersReady = useStickersReady(); - const emojisReady = useEmojisReady(); - const cover = useCover(); - const title = useTitle(); - const author = useAuthor(); - - return !!(stickersReady && emojisReady && cover && title && author); -}; - -const selectUrl = createSelector( - ({ stickers }: AppState) => stickers.packId, - ({ stickers }: AppState) => stickers.packKey, - (id, key) => `https://signal.art/addstickers/#pack_id=${id}&pack_key=${key}` -); - -export const usePackUrl = (): string => useSelector(selectUrl); - -export const useToasts = (): Array => - useSelector(({ stickers }: AppState) => stickers.toasts); - -export const useAddMoreCount = (): number => - useSelector(({ stickers }: AppState) => - clamp(minStickers - stickers.order.length, 0, minStickers) - ); - -const selectOrderedData = createSelector( - ({ stickers }: AppState) => stickers.order, - ({ stickers }: AppState) => stickers.data, - (order, data) => - order.map(id => ({ - ...data[id], - emoji: convertShortName( - (data[id].emoji as EmojiPickDataType).shortName, - (data[id].emoji as EmojiPickDataType).skinTone - ), - })) -); - -export const useSelectOrderedData = (): Array => - useSelector(selectOrderedData); - -const selectOrderedImagePaths = createSelector( - selectOrderedData, - (data: Array) => - data.map(({ imageData }) => imageData?.src).filter(isNotNil) -); - -export const useOrderedImagePaths = (): Array => - useSelector(selectOrderedImagePaths); - -export const useStickerActions = (): Actions => { - const dispatch = useDispatch(); - - return useMemo( - () => - bindActionCreators( - { - addImageData, - initializeStickers, - removeSticker, - moveSticker, - setCover, - setEmoji, - setTitle, - setAuthor, - setPackMeta, - addToast, - dismissToast, - reset, - resetStatus, - }, - dispatch - ), - [dispatch] - ); -}; diff --git a/sticker-creator/store/index.ts b/sticker-creator/store/index.ts deleted file mode 100644 index f82408e2b336..000000000000 --- a/sticker-creator/store/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import { createStore } from 'redux'; -import { reducer } from './reducer'; - -import * as stickersDuck from './ducks/stickers'; - -export { stickersDuck }; - -export const store = createStore(reducer); diff --git a/sticker-creator/store/reducer.ts b/sticker-creator/store/reducer.ts deleted file mode 100644 index 1d7ddbde8d26..000000000000 --- a/sticker-creator/store/reducer.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import type { Reducer } from 'redux'; -import { combineReducers } from 'redux'; -import { reducer as stickers } from './ducks/stickers'; - -export const reducer = combineReducers({ - stickers, -}); - -export type AppState = typeof reducer extends Reducer ? U : never; diff --git a/sticker-creator/util/history.ts b/sticker-creator/util/history.ts deleted file mode 100644 index 2bebc1578368..000000000000 --- a/sticker-creator/util/history.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import { createMemoryHistory } from 'history'; - -export const history = createMemoryHistory(); diff --git a/sticker-creator/util/i18n.tsx b/sticker-creator/util/i18n.tsx deleted file mode 100644 index dfd45000ae18..000000000000 --- a/sticker-creator/util/i18n.tsx +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as React from 'react'; -import type { LocaleMessagesType } from '../../ts/types/I18N'; -import type { LocalizerType, ReplacementValuesType } from '../../ts/types/Util'; -import { - classifyMessages, - createCachedIntl, - formatIcuMessage, -} from '../../ts/util/setupI18n'; - -const placeholder = () => 'NO LOCALE LOADED'; -placeholder.getLocale = () => 'none'; -placeholder.isLegacyFormat = () => { - throw new Error("Can't call isLegacyFormat on placeholder"); -}; -placeholder.getIntl = () => { - throw new Error("Can't call getIntl on placeholder"); -}; - -const I18nContext = React.createContext(placeholder); - -export type I18nProps = { - children: React.ReactNode; - locale: string; - messages: LocaleMessagesType; -}; - -export function I18n({ messages, locale, children }: I18nProps): JSX.Element { - const { icuMessages, legacyMessages } = React.useMemo(() => { - return classifyMessages(messages); - }, [messages]); - const intl = React.useMemo(() => { - return createCachedIntl(locale, icuMessages); - }, [locale, icuMessages]); - - const callback = (key: string, substitutions?: ReplacementValuesType) => { - if (Array.isArray(substitutions) && substitutions.length > 1) { - throw new Error( - 'Array syntax is not supported with more than one placeholder' - ); - } - - const messageformat = icuMessages[key]; - if (messageformat != null) { - return formatIcuMessage(intl, key, substitutions); - } - - const message = legacyMessages[key]; - if (message == null) { - window.SignalContext.log.warn( - `getMessage: No string found for key ${key}` - ); - return ''; - } - if (!substitutions) { - return message; - } - if (Array.isArray(substitutions)) { - return substitutions.reduce( - (result, substitution) => - result.toString().replace(/\$.+?\$/, substitution.toString()), - message - ) as string; - } - - const FIND_REPLACEMENTS = /\$([^$]+)\$/g; - - let match = FIND_REPLACEMENTS.exec(message); - let builder = ''; - let lastTextIndex = 0; - - while (match) { - if (lastTextIndex < match.index) { - builder += message.slice(lastTextIndex, match.index); - } - - const placeholderName = match[1]; - const value = substitutions[placeholderName]; - if (!value) { - // eslint-disable-next-line no-console - console.error( - `i18n: Value not provided for placeholder ${placeholderName} in key '${key}'` - ); - } - builder += value || ''; - - lastTextIndex = FIND_REPLACEMENTS.lastIndex; - match = FIND_REPLACEMENTS.exec(message); - } - - if (lastTextIndex < message.length) { - builder += message.slice(lastTextIndex); - } - - return builder; - }; - callback.getLocale = () => locale; - callback.isLegacyFormat = (key: string) => { - return legacyMessages[key] != null; - }; - callback.getIntl = () => intl; - - const getMessage = React.useCallback(callback, [ - icuMessages, - legacyMessages, - intl, - ]); - - return ( - {children} - ); -} - -export const useI18n = (): LocalizerType => React.useContext(I18nContext); diff --git a/sticker-creator/util/preload.ts b/sticker-creator/util/preload.ts deleted file mode 100644 index 5b2639158d8b..000000000000 --- a/sticker-creator/util/preload.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import type { - ProcessStickerImageErrorType, - StickerImageData, -} from '../window/phase3-sticker-functions'; - -declare global { - // We want to extend `window`'s properties, so we need an interface. - // eslint-disable-next-line no-restricted-syntax - interface Window { - processStickerImage: ProcessStickerImageFn; - encryptAndUpload: EncryptAndUploadFn; - ProcessStickerImageError: ProcessStickerImageErrorType; - } -} - -export { StickerImageData }; - -type ProcessStickerImageFn = ( - path: string | undefined -) => Promise; - -export type StickerData = { imageData?: StickerImageData; emoji?: string }; -export type PackMetaData = { packId: string; key: string }; - -export type EncryptAndUploadFn = ( - manifest: { title: string; author: string }, - stickers: Array, - cover: StickerImageData, - onProgress?: () => unknown -) => Promise; - -export const { encryptAndUpload, processStickerImage } = window; diff --git a/sticker-creator/util/useStickerDropzone.ts b/sticker-creator/util/useStickerDropzone.ts deleted file mode 100644 index c68932c92c90..000000000000 --- a/sticker-creator/util/useStickerDropzone.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2020 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import type { DropzoneOptions } from 'react-dropzone'; -import { useDropzone } from 'react-dropzone'; - -export const useStickerDropzone = ( - onDrop: DropzoneOptions['onDrop'] -): ReturnType => - useDropzone({ - onDrop, - accept: [ - 'image/png', - 'image/webp', - // Some OSes recognize .apng files with the MIME type but others don't, so we supply - // the extension too. - 'image/apng', - '.apng', - ], - }); diff --git a/sticker-creator/window/phase1-dependencies.ts b/sticker-creator/window/phase1-dependencies.ts deleted file mode 100644 index e3185c0dd0b1..000000000000 --- a/sticker-creator/window/phase1-dependencies.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2022 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import Backbone from 'backbone'; - -import { ipcRenderer as ipc } from 'electron'; - -// It is important to call this as early as possible -import { SignalContext } from '../../ts/windows/context'; - -import { getEnvironment } from '../../ts/environment'; - -SignalContext.log.info('sticker-creator starting up...'); - -window.ROOT_PATH = window.location.href.startsWith('file') ? '../../' : '/'; -window.getEnvironment = getEnvironment; -window.getVersion = () => window.SignalContext.config.version; - -window.Backbone = Backbone; - -window.localeMessages = ipc.sendSync('locale-data'); diff --git a/sticker-creator/window/phase2-signal.ts b/sticker-creator/window/phase2-signal.ts deleted file mode 100644 index 91e9d1762664..000000000000 --- a/sticker-creator/window/phase2-signal.ts +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2022 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as Signal from '../../ts/signal'; -import { textsecure } from '../../ts/textsecure'; - -import * as Attachments from '../../ts/windows/attachments'; -import '../../ts/SignalProtocolStore'; - -import { SignalContext } from '../../ts/windows/context'; - -window.Signal = Signal.setup({ - Attachments, - getRegionCode: () => { - throw new Error('Sticker Creator preload: Not implemented!'); - }, - logger: SignalContext.log, - userDataPath: SignalContext.config.userDataPath, -}); -window.textsecure = textsecure; diff --git a/sticker-creator/window/phase3-sticker-functions.ts b/sticker-creator/window/phase3-sticker-functions.ts deleted file mode 100644 index 63539f6ba7fe..000000000000 --- a/sticker-creator/window/phase3-sticker-functions.ts +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright 2022 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import { readFile } from 'fs/promises'; -import { noop, uniqBy } from 'lodash'; -import { ipcRenderer as ipc } from 'electron'; - -import { - deriveStickerPackKey, - encryptAttachment, - getRandomBytes, -} from '../../ts/Crypto'; -import * as Bytes from '../../ts/Bytes'; -import { SignalService as Proto } from '../../ts/protobuf'; -import { initialize as initializeWebAPI } from '../../ts/textsecure/WebAPI'; - -import { SignalContext } from '../../ts/windows/context'; -import { getAnimatedPngDataIfExists } from '../../ts/util/getAnimatedPngDataIfExists'; -import { explodePromise } from '../../ts/util/explodePromise'; - -class ProcessStickerImageError extends Error { - constructor(message: string, public readonly errorMessageI18nKey: string) { - super(message); - } -} -export type ProcessStickerImageErrorType = typeof ProcessStickerImageError; -window.ProcessStickerImageError = ProcessStickerImageError; - -const STICKER_SIZE = 512; -const MIN_STICKER_DIMENSION = 10; -const MAX_STICKER_DIMENSION = STICKER_SIZE; -const MAX_STICKER_BYTE_LENGTH = 300 * 1024; - -const { config } = SignalContext; - -const WebAPI = initializeWebAPI({ - url: config.serverUrl, - storageUrl: config.storageUrl, - updatesUrl: config.updatesUrl, - resourcesUrl: config.resourcesUrl, - artCreatorUrl: config.artCreatorUrl, - directoryConfig: config.directoryConfig, - cdnUrlObject: { - 0: config.cdnUrl0, - 2: config.cdnUrl2, - }, - certificateAuthority: config.certificateAuthority, - contentProxyUrl: config.contentProxyUrl, - proxyUrl: config.proxyUrl, - version: config.version, -}); - -export type StickerImageData = Readonly<{ - buffer: Buffer; - src: string; - path: string; -}>; - -async function loadImage(data: Buffer): Promise { - const image = new Image(); - - const { promise, resolve, reject } = explodePromise(); - - image.addEventListener('load', () => resolve()); - image.addEventListener('error', () => reject(new Error('Bad image'))); - image.src = `data:image/jpeg;base64,${data.toString('base64')}`; - - await promise; - - return image; -} - -declare global { - // eslint-disable-next-line no-restricted-syntax - interface OffscreenCanvas { - convertToBlob(options: { type: string; quality: number }): Promise; - } -} - -window.processStickerImage = async function processStickerImage( - path?: string -): Promise { - if (!path) { - throw new Error(`Path ${path} is not valid!`); - } - - const imgBuffer = await readFile(path); - - const image = await loadImage(imgBuffer); - const { naturalWidth: width, naturalHeight: height } = image; - if (!width || !height) { - throw new ProcessStickerImageError( - 'Sticker height or width were falsy', - 'StickerCreator--Toasts--errorProcessing' - ); - } - - let contentType; - let processedBuffer; - - // For APNG we do something simpler: validate the file size - // and dimensions without resizing, cropping, or converting. In a perfect world, we'd - // resize and convert any animated image (GIF, animated WebP) to APNG. - const animatedPngDataIfExists = getAnimatedPngDataIfExists(imgBuffer); - if (animatedPngDataIfExists) { - if (imgBuffer.byteLength > MAX_STICKER_BYTE_LENGTH) { - throw new ProcessStickerImageError( - 'Sticker file was too large', - 'StickerCreator--Toasts--tooLarge' - ); - } - if (width !== height) { - throw new ProcessStickerImageError( - 'Sticker must be square', - 'StickerCreator--Toasts--APNG--notSquare' - ); - } - if (width > MAX_STICKER_DIMENSION) { - throw new ProcessStickerImageError( - 'Sticker dimensions are too large', - 'StickerCreator--Toasts--APNG--dimensionsTooLarge' - ); - } - if (width < MIN_STICKER_DIMENSION) { - throw new ProcessStickerImageError( - 'Sticker dimensions are too small', - 'StickerCreator--Toasts--APNG--dimensionsTooSmall' - ); - } - if (animatedPngDataIfExists.numPlays !== Infinity) { - throw new ProcessStickerImageError( - 'Animated stickers must loop forever', - 'StickerCreator--Toasts--mustLoopForever' - ); - } - contentType = 'image/png'; - processedBuffer = imgBuffer; - } else { - const canvas = new OffscreenCanvas(STICKER_SIZE, STICKER_SIZE); - const context = canvas.getContext('2d'); - if (!context) { - throw new Error('Failed to get 2d context of canvas'); - } - - const scaleFactor = STICKER_SIZE / Math.max(width, height); - const newWidth = width * scaleFactor; - const newHeight = height * scaleFactor; - const dx = (STICKER_SIZE - newWidth) / 2; - const dy = (STICKER_SIZE - newHeight) / 2; - - (context as OffscreenCanvasRenderingContext2D).drawImage( - image, - dx, - dy, - newWidth, - newHeight - ); - - const blob = await canvas.convertToBlob({ - type: 'image/webp', - quality: 0.8, - }); - - processedBuffer = Buffer.from(await blob.arrayBuffer()); - - if ( - !processedBuffer || - processedBuffer.byteLength > MAX_STICKER_BYTE_LENGTH - ) { - throw new ProcessStickerImageError( - 'Sticker file was too large', - 'StickerCreator--Toasts--tooLarge' - ); - } - } - - return { - path, - buffer: processedBuffer, - src: `data:${contentType};base64,${processedBuffer.toString('base64')}`, - }; -}; - -window.encryptAndUpload = async ( - manifest, - stickers, - cover, - onProgress = noop -) => { - const usernameItem = await window.Signal.Data.getItemById('uuid_id'); - const oldUsernameItem = await window.Signal.Data.getItemById('number_id'); - const passwordItem = await window.Signal.Data.getItemById('password'); - - const username = usernameItem?.value || oldUsernameItem?.value; - if (!username || !passwordItem?.value) { - const { message } = - window.localeMessages['StickerCreator--Authentication--error']; - - ipc.send('show-message-box', { - type: 'warning', - message, - }); - - throw new Error(message); - } - - const { value: password } = passwordItem; - - const packKey = getRandomBytes(32); - const encryptionKey = deriveStickerPackKey(packKey); - - const server = WebAPI.connect({ - username, - password, - useWebSocket: false, - hasStoriesDisabled: true, - }); - - const manifestProto = new Proto.StickerPack(); - manifestProto.title = manifest.title; - manifestProto.author = manifest.author; - manifestProto.stickers = stickers.map(({ emoji }, id) => { - const s = new Proto.StickerPack.Sticker(); - s.id = id; - if (emoji) { - s.emoji = emoji; - } - - return s; - }); - - const uniqueStickers = uniqBy( - [...stickers, { imageData: cover }], - 'imageData' - ); - const coverStickerIndex = uniqueStickers.findIndex( - item => item.imageData?.src === cover.src - ); - const coverStickerId = coverStickerIndex >= 0 ? coverStickerIndex : 0; - const coverStickerData = stickers[coverStickerId]; - - if (!coverStickerData) { - window.SignalContext.log.warn( - 'encryptAndUpload: No coverStickerData with ' + - `index ${coverStickerId} and ${stickers.length} total stickers` - ); - } - - const coverSticker = new Proto.StickerPack.Sticker(); - coverSticker.id = coverStickerId; - - if (coverStickerData?.emoji && coverSticker) { - coverSticker.emoji = coverStickerData.emoji; - } else { - coverSticker.emoji = ''; - } - - manifestProto.cover = coverSticker; - - const encryptedManifest = await encrypt( - Proto.StickerPack.encode(manifestProto).finish(), - encryptionKey - ); - const encryptedStickers = uniqueStickers.map(({ imageData }) => { - if (!imageData?.buffer) { - throw new Error('encryptStickers: Missing image data on sticker'); - } - - return encrypt(imageData.buffer, encryptionKey); - }); - - const packId = await server.putStickers( - encryptedManifest, - encryptedStickers, - onProgress - ); - - const hexKey = Bytes.toHex(packKey); - - ipc.send('install-sticker-pack', packId, hexKey); - - return { packId, key: hexKey }; -}; - -function encrypt(data: Uint8Array, key: Uint8Array): Uint8Array { - const { ciphertext } = encryptAttachment(data, key); - - return ciphertext; -} diff --git a/sticker-creator/window/phase4-theme.ts b/sticker-creator/window/phase4-theme.ts deleted file mode 100644 index 7480452bbdc3..000000000000 --- a/sticker-creator/window/phase4-theme.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2022 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import { createSetting } from '../../ts/util/preload'; -import { SignalContext } from '../../ts/windows/context'; - -const getThemeSetting = createSetting('themeSetting'); - -async function resolveTheme() { - const theme = (await getThemeSetting.getValue()) || 'system'; - if (theme === 'system') { - return SignalContext.nativeThemeListener.getSystemTheme(); - } - return theme; -} - -async function applyTheme() { - window.document.body.classList.remove('dark-theme'); - window.document.body.classList.remove('light-theme'); - window.document.body.classList.add(`${await resolveTheme()}-theme`); -} - -window.addEventListener('DOMContentLoaded', applyTheme); - -SignalContext.nativeThemeListener.subscribe(() => applyTheme()); diff --git a/ts/background.ts b/ts/background.ts index 9f6fb95e07da..b6d94e430a66 100644 --- a/ts/background.ts +++ b/ts/background.ts @@ -1082,7 +1082,6 @@ export async function startApp(): Promise { devTools: false, includeSetup: false, isProduction: true, - isStaging: false, platform: 'unknown', }; diff --git a/ts/components/TitleBarContainer.tsx b/ts/components/TitleBarContainer.tsx index 4f6a5faf8a52..1ef648fafd8b 100644 --- a/ts/components/TitleBarContainer.tsx +++ b/ts/components/TitleBarContainer.tsx @@ -34,9 +34,6 @@ export type PropsType = Readonly<{ executeMenuRole: ExecuteMenuRoleType; titleBarDoubleClick?: () => void; children: ReactNode; - - // Needs to be overridden in sticker-creator - iconSrc?: string; }> & (MenuPropsType | { hasMenu?: false }); @@ -132,7 +129,6 @@ export function TitleBarContainer(props: PropsType): JSX.Element { titleBarDoubleClick, children, hasMenu, - iconSrc = 'images/icon_32.png', } = props; const isWindowActive = useIsWindowActive(); @@ -238,7 +234,6 @@ export function TitleBarContainer(props: PropsType): JSX.Element { showDebugLog: () => executeMenuAction('showDebugLog'), showKeyboardShortcuts: () => executeMenuAction('showKeyboardShortcuts'), showSettings: () => executeMenuAction('showSettings'), - showStickerCreator: () => executeMenuAction('showStickerCreator'), showWindow: () => executeMenuAction('showWindow'), }, i18n @@ -261,7 +256,7 @@ export function TitleBarContainer(props: PropsType): JSX.Element { { showDebugLog, showKeyboardShortcuts, showSettings, - showStickerCreator, showWindow, }; @@ -238,7 +236,6 @@ describe('createTemplate', () => { devTools: true, includeSetup: false, isProduction: true, - isStaging: false, platform, ...actions, }; @@ -253,7 +250,6 @@ describe('createTemplate', () => { devTools: true, includeSetup: true, isProduction: true, - isStaging: false, platform, ...actions, }; diff --git a/ts/test-node/util/getAnimatedPngDataIfExists_test.ts b/ts/test-node/util/getAnimatedPngDataIfExists_test.ts deleted file mode 100644 index 58235dcd6492..000000000000 --- a/ts/test-node/util/getAnimatedPngDataIfExists_test.ts +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2020 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import * as fs from 'fs'; -import * as path from 'path'; -import { assert } from 'chai'; - -import { getAnimatedPngDataIfExists } from '../../util/getAnimatedPngDataIfExists'; - -describe('getAnimatedPngDataIfExists', () => { - const fixture = (filename: string): Promise => { - const fixturePath = path.join( - __dirname, - '..', - '..', - '..', - 'fixtures', - filename - ); - return fs.promises.readFile(fixturePath); - }; - - it('returns null for empty buffers', () => { - assert.isNull(getAnimatedPngDataIfExists(Buffer.alloc(0))); - }); - - it('returns null for non-PNG files', async () => { - await Promise.all( - [ - 'kitten-1-64-64.jpg', - '512x515-thumbs-up-lincoln.webp', - 'giphy-GVNvOUpeYmI7e.gif', - 'pixabay-Soap-Bubble-7141.mp4', - 'lorem-ipsum.txt', - ].map(async filename => { - assert.isNull(getAnimatedPngDataIfExists(await fixture(filename))); - }) - ); - }); - - it('returns null for non-animated PNG files', async () => { - assert.isNull( - getAnimatedPngDataIfExists(await fixture('20x200-yellow.png')) - ); - }); - - it('returns data for animated PNG files', async () => { - assert.deepEqual( - getAnimatedPngDataIfExists( - await fixture('Animated_PNG_example_bouncing_beach_ball.png') - ), - { numPlays: Infinity } - ); - - assert.deepEqual( - getAnimatedPngDataIfExists(await fixture('apng_with_2_plays.png')), - { numPlays: 2 } - ); - }); -}); diff --git a/ts/types/menu.ts b/ts/types/menu.ts index df01b149ebf1..eda3ebb26d6f 100644 --- a/ts/types/menu.ts +++ b/ts/types/menu.ts @@ -10,7 +10,6 @@ export type MenuOptionsType = Readonly<{ devTools: boolean; includeSetup: boolean; isProduction: boolean; - isStaging: boolean; platform: string; }>; @@ -28,7 +27,6 @@ export type MenuActionsType = Readonly<{ showDebugLog: () => unknown; showKeyboardShortcuts: () => unknown; showSettings: () => unknown; - showStickerCreator: () => unknown; showWindow: () => unknown; }>; diff --git a/ts/util/getAnimatedPngDataIfExists.ts b/ts/util/getAnimatedPngDataIfExists.ts deleted file mode 100644 index 05bbe755f3a2..000000000000 --- a/ts/util/getAnimatedPngDataIfExists.ts +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright 2020 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -const PNG_SIGNATURE = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]); -const ACTL_CHUNK_BYTES = new TextEncoder().encode('acTL'); -const IDAT_CHUNK_BYTES = new TextEncoder().encode('IDAT'); -const MAX_BYTES_TO_READ = 1024 * 1024; - -type AnimatedPngData = { - numPlays: number; -}; - -/** - * This is a naïve implementation. It only performs two checks: - * - * 1. Do the bytes start with the [PNG signature][0]? - * 2. If so, does it contain the [`acTL` chunk][1] before the [`IDAT` chunk][2], in the - * first megabyte? - * - * Though we _could_ only check for the presence of the `acTL` chunk anywhere, we make - * sure it's before the `IDAT` chunk and within the first megabyte. This adds a small - * amount of validity checking and helps us avoid problems with large PNGs. - * - * It doesn't make sure the PNG is valid. It doesn't verify [the CRC code][3] of each PNG - * chunk; it doesn't verify any of the chunk's data; it doesn't verify that the chunks are - * in the right order; etc. - * - * [0]: https://www.w3.org/TR/PNG/#5PNG-file-signature - * [1]: https://wiki.mozilla.org/APNG_Specification#.60acTL.60:_The_Animation_Control_Chunk - * [2]: https://www.w3.org/TR/PNG/#11IDAT - * [3]: https://www.w3.org/TR/PNG/#5Chunk-layout - */ -export function getAnimatedPngDataIfExists( - bytes: Uint8Array -): null | AnimatedPngData { - if (!hasPngSignature(bytes)) { - return null; - } - - let numPlays: void | number; - - const dataView = new DataView( - bytes.buffer, - bytes.byteOffset, - bytes.byteLength - ); - - let i = PNG_SIGNATURE.length; - while (i < bytes.byteLength && i <= MAX_BYTES_TO_READ) { - const chunkTypeBytes = bytes.slice(i + 4, i + 8); - if (areBytesEqual(chunkTypeBytes, ACTL_CHUNK_BYTES)) { - // 4 bytes for the length; 4 bytes for the type; 4 bytes for the number of frames. - numPlays = dataView.getUint32(i + 12); - if (numPlays === 0) { - numPlays = Infinity; - } - return { numPlays }; - } - if (areBytesEqual(chunkTypeBytes, IDAT_CHUNK_BYTES)) { - return null; - } - - // Jump over the length (4 bytes), the type (4 bytes), the data, and the CRC checksum - // (4 bytes). - i += 12 + dataView.getUint32(i); - } - - return null; -} - -function hasPngSignature(bytes: Uint8Array): boolean { - return areBytesEqual(bytes.slice(0, 8), PNG_SIGNATURE); -} - -function areBytesEqual(a: Uint8Array, b: Uint8Array): boolean { - if (a.byteLength !== b.byteLength) { - return false; - } - for (let i = 0; i < a.byteLength; i += 1) { - if (a[i] !== b[i]) { - return false; - } - } - return true; -} diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index c30adb2343bc..8abf844f655e 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -1783,20 +1783,6 @@ "updated": "2021-09-16T20:26:31.296Z", "reasonDetail": "Dev-only dependency." }, - { - "rule": "React-useRef", - "path": "sticker-creator/components/StickerFrame.js", - "line": " const timerRef = React.useRef();", - "reasonCategory": "falseMatch", - "updated": "2022-06-14T01:19:45.446Z" - }, - { - "rule": "React-useRef", - "path": "sticker-creator/components/StickerFrame.tsx", - "line": " const timerRef = React.useRef();", - "reasonCategory": "usageTrusted", - "updated": "2021-07-30T16:57:33.618Z" - }, { "rule": "React-useRef", "path": "ts/calling/useGetCallingFrameBuffer.ts", diff --git a/ts/util/lint/linter.ts b/ts/util/lint/linter.ts index d4ed74b7c218..6eb564ea39b6 100644 --- a/ts/util/lint/linter.ts +++ b/ts/util/lint/linter.ts @@ -62,7 +62,6 @@ const excludedFilesRegexp = RegExp( '^js/curve/', '^js/util_worker.js', '^libtextsecure/test/test.js', - '^sticker-creator/dist/bundle.js', '^test/test.js', '^ts/workers/heicConverter.bundle.js', '^ts/sql/mainWorker.bundle.js', @@ -87,7 +86,6 @@ const excludedFilesRegexp = RegExp( '^node_modules/react/.+', '^node_modules/react-contextmenu/.+', '^node_modules/react-dom/.+', - '^node_modules/react-dropzone/.+', '^node_modules/react-hot-loader/.+', '^node_modules/react-icon-base/.+', '^node_modules/react-input-autosize/.+', @@ -97,7 +95,6 @@ const excludedFilesRegexp = RegExp( '^node_modules/react-router/.+', '^node_modules/react-router-dom/.+', '^node_modules/react-select/.+', - '^node_modules/react-sortable-hoc/.+', '^node_modules/react-transition-group/.+', '^node_modules/react-virtualized/.+', '^node_modules/reactcss/.+', @@ -176,7 +173,6 @@ const excludedFilesRegexp = RegExp( '^node_modules/express/.+', '^node_modules/fast-glob/.+', '^node_modules/file-entry-cache/.+', - '^node_modules/file-loader/.+', '^node_modules/file-system-cache/.+', // Currently only used in storybook '^node_modules/finalhandler/.+', '^node_modules/flat-cache/.+', diff --git a/tsconfig.json b/tsconfig.json index dfe7ebea527f..fcc2d6e33553 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -61,11 +61,5 @@ // "experimentalDecorators": true, // Enables experimental support for ES7 decorators. // "emitDecoratorMetadata": true, // Enables experimental support for emitting type metadata for decorators. }, - "include": [ - "ts/**/*", - "app/**/*", - "sticker-creator/**/*", - "package.json", - "build/intl-linter/**/*" - ] + "include": ["ts/**/*", "app/**/*", "package.json", "build/intl-linter/**/*"] } diff --git a/webpack.config.ts b/webpack.config.ts deleted file mode 100644 index a204dfbacb75..000000000000 --- a/webpack.config.ts +++ /dev/null @@ -1,99 +0,0 @@ -// Copyright 2019 Signal Messenger, LLC -// SPDX-License-Identifier: AGPL-3.0-only - -import { resolve } from 'path'; -// eslint-disable-next-line import/no-extraneous-dependencies -import { Configuration, EnvironmentPlugin, ProvidePlugin } from 'webpack'; -import HtmlWebpackPlugin = require('html-webpack-plugin'); -import TerserPlugin = require('terser-webpack-plugin'); - -const context = __dirname; -const { NODE_ENV: mode = 'development' } = process.env; -const isDev = mode === 'development'; - -const csp = ` - default-src 'none'; - child-src 'self'; - connect-src 'self'${isDev ? ' http: ws:' : ''}; - font-src 'self'; - form-action 'self'; - frame-src 'none'; - img-src 'self' blob: data:; - media-src 'self' blob:; - object-src 'none'; - script-src 'self'${isDev ? " 'unsafe-eval'" : ''}; - style-src 'self' 'unsafe-inline'; -`; - -const stickerCreatorConfig: Configuration = { - context, - mode: mode as Configuration['mode'], - entry: [ - 'react-hot-loader/patch', - 'sanitize.css', - 'typeface-inter', - './sticker-creator/index.tsx', - ], - // Stack-traces have to be readable so don't mangle function names. - optimization: { - minimizer: [ - new TerserPlugin({ - parallel: true, - terserOptions: { - mangle: false, - keep_classnames: true, - keep_fnames: true, - }, - }), - ], - }, - output: { - path: resolve(context, 'sticker-creator/dist'), - filename: 'bundle.js', - publicPath: mode === 'production' ? './' : '/sticker-creator/dist/', - }, - module: { - rules: [ - { - test: /\.tsx?$/, - use: [{ loader: 'babel-loader' }], - }, - { - test: /\.css$/, - use: [{ loader: 'style-loader' }, { loader: 'css-loader' }], - }, - { - test: /\.scss$/, - use: [ - { loader: 'style-loader' }, - { loader: 'css-loader?modules=true&localsConvention=camelCaseOnly' }, - { loader: 'sass-loader' }, - ], - }, - { - test: /\.woff2?$/, - use: [{ loader: 'file-loader' }], - }, - ], - }, - resolve: { - extensions: ['.tsx', '.ts', '.jsx', '.js'], - alias: {}, - }, - plugins: [ - new ProvidePlugin({ Buffer: ['buffer', 'Buffer'] }), - new EnvironmentPlugin(['NODE_ENV']), - new HtmlWebpackPlugin({ - title: 'Signal Sticker Creator', - template: resolve(context, 'sticker-creator/index.html'), - meta: { - 'Content-Security-Policy': { - 'http-equiv': 'Content-Security-Policy', - content: csp, - }, - }, - }), - ], -}; - -export default [stickerCreatorConfig]; diff --git a/yarn.lock b/yarn.lock index ae1edc93cdae..3ad12454b0aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4229,13 +4229,6 @@ "@types/history" "*" "@types/react" "*" -"@types/react-sortable-hoc@0.6.5": - version "0.6.5" - resolved "https://registry.yarnpkg.com/@types/react-sortable-hoc/-/react-sortable-hoc-0.6.5.tgz#3f40611427b4dd1ed06f99678a5df7c0f950de29" - integrity sha512-0Ms36xuds/pByIQFobwlDGPaUPSF6jOZUhOqf/0SaX/ZC0z9a/vwwWigEJomTvlshyjlKwB6JXV9TK+8keXq7w== - dependencies: - "@types/react" "*" - "@types/react-syntax-highlighter@11.0.5": version "11.0.5" resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-11.0.5.tgz#0d546261b4021e1f9d85b50401c0a42acb106087" @@ -5504,11 +5497,6 @@ array-includes@^3.1.5: get-intrinsic "^1.1.3" is-string "^1.0.7" -array-move@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-move/-/array-move-2.1.0.tgz#b4e9fc8d6a580bc97dcad408e0539c61b4b7ed7e" - integrity sha512-BXEIud+F7/ech2HcSfo+6bpgSCRlNnVTqQhGKdMov9iJkHq+vu9IP9qRXDpZvQpc1WWpDLiEfjs6Lfvvac+fDA== - array-union@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" @@ -5561,13 +5549,6 @@ array.prototype.flatmap@^1.3.0: es-abstract "^1.20.4" es-shim-unscopables "^1.0.0" -arraybuffer-loader@1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer-loader/-/arraybuffer-loader-1.0.3.tgz#0ef589c60414f1b489e7bda0ebafd2fe329f0a4f" - integrity sha1-DvWJxgQU8bSJ572g66/S/jKfCk8= - dependencies: - loader-utils "^1.1.0" - arrify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" @@ -5680,11 +5661,6 @@ atomic-sleep@^1.0.0: resolved "https://registry.yarnpkg.com/atomic-sleep/-/atomic-sleep-1.0.0.tgz#eb85b77a601fc932cfe432c5acd364a9e2c9075b" integrity sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ== -attr-accept@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/attr-accept/-/attr-accept-2.2.2.tgz#646613809660110749e92f2c10833b70968d929b" - integrity sha512-7prDjvt9HmqiZ0cl5CRjtS84sEyhsHP2coDkaZKRKVfCDo9s7iw7ChVmar78Gu9pC4SoR/28wFu/G5JJhTnqEg== - autoprefixer@^9.8.6: version "9.8.8" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.8.8.tgz#fd4bd4595385fa6f06599de749a4d5f7a474957a" @@ -9362,14 +9338,6 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -file-loader@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-4.2.0.tgz#5fb124d2369d7075d70a9a5abecd12e60a95215e" - integrity sha512-+xZnaK5R8kBJrHK0/6HRlrKNamvVS5rjyuju+rnyxRGuwUJwpAMsVzUl5dz6rK8brkzjV6JpcFNjp6NqV0g1OQ== - dependencies: - loader-utils "^1.2.3" - schema-utils "^2.0.0" - file-loader@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" @@ -9378,13 +9346,6 @@ file-loader@^6.2.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -file-selector@^0.1.12: - version "0.1.19" - resolved "https://registry.yarnpkg.com/file-selector/-/file-selector-0.1.19.tgz#8ecc9d069a6f544f2e4a096b64a8052e70ec8abf" - integrity sha512-kCWw3+Aai8Uox+5tHCNgMFaUdgidxvMnLWO6fM5sZ0hA2wlHP5/DHGF0ECe84BiB95qdJbKNEJhWKVDvMN+JDQ== - dependencies: - tslib "^2.0.1" - file-system-cache@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/file-system-cache/-/file-system-cache-1.0.5.tgz#84259b36a2bbb8d3d6eb1021d3132ffe64cfff4f" @@ -14945,7 +14906,7 @@ prop-types@^15.0.0, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -prop-types@^15.5.7, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: +prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2: version "15.7.2" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== @@ -15280,15 +15241,6 @@ react-dom@17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" -react-dropzone@10.2.2: - version "10.2.2" - resolved "https://registry.yarnpkg.com/react-dropzone/-/react-dropzone-10.2.2.tgz#67b4db7459589a42c3b891a82eaf9ade7650b815" - integrity sha512-U5EKckXVt6IrEyhMMsgmHQiWTGLudhajPPG77KFSvgsMqNEHSyGpqWvOMc5+DhEah/vH4E1n+J5weBNLd5VtyA== - dependencies: - attr-accept "^2.0.0" - file-selector "^0.1.12" - prop-types "^15.7.2" - react-element-to-jsx-string@^14.3.4: version "14.3.4" resolved "https://registry.yarnpkg.com/react-element-to-jsx-string/-/react-element-to-jsx-string-14.3.4.tgz#709125bc72f06800b68f9f4db485f2c7d31218a8" @@ -15466,15 +15418,6 @@ react-sizeme@^3.0.1: shallowequal "^1.1.0" throttle-debounce "^3.0.1" -react-sortable-hoc@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/react-sortable-hoc/-/react-sortable-hoc-2.0.0.tgz#f6780d8aa4b922a21f3e754af542f032677078b7" - integrity sha512-JZUw7hBsAHXK7PTyErJyI7SopSBFRcFHDjWW5SWjcugY0i6iH7f+eJkY8cJmGMlZ1C9xz1J3Vjz0plFpavVeRg== - dependencies: - "@babel/runtime" "^7.2.0" - invariant "^2.2.4" - prop-types "^15.5.7" - react-syntax-highlighter@^15.4.5: version "15.5.0" resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.5.0.tgz#4b3eccc2325fa2ec8eff1e2d6c18fa4a9e07ab20"