From 24ef8255b3f9b44cb54f49bc78fe3382a7070b1a Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 12 Sep 2024 14:54:16 +0200 Subject: [PATCH] Change design of embed modal in web UI (#31801) --- .../mastodon/components/copy_paste_text.tsx | 90 ++++++++++++++ .../mastodon/components/status_action_bar.jsx | 2 +- .../mastodon/containers/status_container.jsx | 6 +- .../mastodon/features/onboarding/share.jsx | 63 +--------- .../features/status/components/action_bar.jsx | 2 +- .../features/ui/components/embed_modal.jsx | 101 --------------- .../features/ui/components/embed_modal.tsx | 116 ++++++++++++++++++ app/javascript/mastodon/locales/en.json | 2 +- .../styles/mastodon/components.scss | 111 ++++++++--------- app/serializers/oembed_serializer.rb | 17 ++- app/views/layouts/embedded.html.haml | 2 +- .../initializers/content_security_policy.rb | 11 +- 12 files changed, 278 insertions(+), 245 deletions(-) create mode 100644 app/javascript/mastodon/components/copy_paste_text.tsx delete mode 100644 app/javascript/mastodon/features/ui/components/embed_modal.jsx create mode 100644 app/javascript/mastodon/features/ui/components/embed_modal.tsx diff --git a/app/javascript/mastodon/components/copy_paste_text.tsx b/app/javascript/mastodon/components/copy_paste_text.tsx new file mode 100644 index 000000000..f888acd0f --- /dev/null +++ b/app/javascript/mastodon/components/copy_paste_text.tsx @@ -0,0 +1,90 @@ +import { useRef, useState, useCallback } from 'react'; + +import { FormattedMessage } from 'react-intl'; + +import classNames from 'classnames'; + +import ContentCopyIcon from '@/material-icons/400-24px/content_copy.svg?react'; +import { useTimeout } from 'mastodon/../hooks/useTimeout'; +import { Icon } from 'mastodon/components/icon'; + +export const CopyPasteText: React.FC<{ value: string }> = ({ value }) => { + const inputRef = useRef(null); + const [copied, setCopied] = useState(false); + const [focused, setFocused] = useState(false); + const [setAnimationTimeout] = useTimeout(); + + const handleInputClick = useCallback(() => { + setCopied(false); + + if (inputRef.current) { + inputRef.current.focus(); + inputRef.current.select(); + inputRef.current.setSelectionRange(0, value.length); + } + }, [setCopied, value]); + + const handleButtonClick = useCallback( + (e: React.MouseEvent) => { + e.stopPropagation(); + void navigator.clipboard.writeText(value); + inputRef.current?.blur(); + setCopied(true); + setAnimationTimeout(() => { + setCopied(false); + }, 700); + }, + [setCopied, setAnimationTimeout, value], + ); + + const handleKeyUp = useCallback( + (e: React.KeyboardEvent) => { + if (e.key !== ' ') return; + void navigator.clipboard.writeText(value); + setCopied(true); + setAnimationTimeout(() => { + setCopied(false); + }, 700); + }, + [setCopied, setAnimationTimeout, value], + ); + + const handleFocus = useCallback(() => { + setFocused(true); + }, [setFocused]); + + const handleBlur = useCallback(() => { + setFocused(false); + }, [setFocused]); + + return ( +
+