Merge pull request #2625 from ClearlyClaire/glitch-soc/ports/copy-button-on-profile
Add prominent share/copy button on profiles in web UIpull/2627/head
commit
5c0a64a975
|
@ -0,0 +1,43 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import { useState, useCallback } from 'react';
|
||||
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { useDispatch } from 'react-redux';
|
||||
|
||||
import ContentCopyIcon from '@/material-icons/400-24px/content_copy.svg?react';
|
||||
import { showAlert } from 'flavours/glitch/actions/alerts';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
|
||||
const messages = defineMessages({
|
||||
copied: { id: 'copy_icon_button.copied', defaultMessage: 'Copied to clipboard' },
|
||||
});
|
||||
|
||||
export const CopyIconButton = ({ title, value, className }) => {
|
||||
const [copied, setCopied] = useState(false);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
navigator.clipboard.writeText(value);
|
||||
setCopied(true);
|
||||
dispatch(showAlert({ message: messages.copied }));
|
||||
setTimeout(() => setCopied(false), 700);
|
||||
}, [setCopied, value, dispatch]);
|
||||
|
||||
return (
|
||||
<IconButton
|
||||
className={classNames(className, copied ? 'copied' : 'copyable')}
|
||||
title={title}
|
||||
onClick={handleClick}
|
||||
iconComponent={ContentCopyIcon}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
CopyIconButton.propTypes = {
|
||||
title: PropTypes.string,
|
||||
value: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
};
|
|
@ -14,9 +14,11 @@ import LockIcon from '@/material-icons/400-24px/lock.svg?react';
|
|||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
import NotificationsIcon from '@/material-icons/400-24px/notifications.svg?react';
|
||||
import NotificationsActiveIcon from '@/material-icons/400-24px/notifications_active-fill.svg?react';
|
||||
import ShareIcon from '@/material-icons/400-24px/share.svg?react';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import { Badge, AutomatedBadge, GroupBadge } from 'flavours/glitch/components/badge';
|
||||
import { Button } from 'flavours/glitch/components/button';
|
||||
import { CopyIconButton } from 'flavours/glitch/components/copy_icon_button';
|
||||
import { Icon } from 'flavours/glitch/components/icon';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
import DropdownMenuContainer from 'flavours/glitch/containers/dropdown_menu_container';
|
||||
|
@ -44,6 +46,7 @@ const messages = defineMessages({
|
|||
mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' },
|
||||
report: { id: 'account.report', defaultMessage: 'Report @{name}' },
|
||||
share: { id: 'account.share', defaultMessage: 'Share @{name}\'s profile' },
|
||||
copy: { id: 'account.copy', defaultMessage: 'Copy link to profile' },
|
||||
media: { id: 'account.media', defaultMessage: 'Media' },
|
||||
blockDomain: { id: 'account.block_domain', defaultMessage: 'Block domain {domain}' },
|
||||
unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
|
||||
|
@ -175,11 +178,10 @@ class Header extends ImmutablePureComponent {
|
|||
const isRemote = account.get('acct') !== account.get('username');
|
||||
const remoteDomain = isRemote ? account.get('acct').split('@')[1] : null;
|
||||
|
||||
let info = [];
|
||||
let actionBtn = '';
|
||||
let bellBtn = '';
|
||||
let lockedIcon = '';
|
||||
let menu = [];
|
||||
let actionBtn, bellBtn, lockedIcon, shareBtn;
|
||||
|
||||
let info = [];
|
||||
let menu = [];
|
||||
|
||||
if (me !== account.get('id') && account.getIn(['relationship', 'followed_by'])) {
|
||||
info.push(<span className='relationship-tag'><FormattedMessage id='account.follows_you' defaultMessage='Follows you' /></span>);
|
||||
|
@ -197,6 +199,12 @@ class Header extends ImmutablePureComponent {
|
|||
bellBtn = <IconButton icon={account.getIn(['relationship', 'notifying']) ? 'bell' : 'bell-o'} iconComponent={account.getIn(['relationship', 'notifying']) ? NotificationsActiveIcon : NotificationsIcon} active={account.getIn(['relationship', 'notifying'])} title={intl.formatMessage(account.getIn(['relationship', 'notifying']) ? messages.disableNotifications : messages.enableNotifications, { name: account.get('username') })} onClick={this.props.onNotifyToggle} />;
|
||||
}
|
||||
|
||||
if ('share' in navigator) {
|
||||
shareBtn = <IconButton className='optional' iconComponent={ShareIcon} title={intl.formatMessage(messages.share, { name: account.get('username') })} onClick={this.handleShare} />;
|
||||
} else {
|
||||
shareBtn = <CopyIconButton className='optional' title={intl.formatMessage(messages.copy)} value={account.get('url')} />;
|
||||
}
|
||||
|
||||
if (me !== account.get('id')) {
|
||||
if (signedIn && !account.get('relationship')) { // Wait until the relationship is loaded
|
||||
actionBtn = '';
|
||||
|
@ -234,11 +242,6 @@ class Header extends ImmutablePureComponent {
|
|||
menu.push(null);
|
||||
}
|
||||
|
||||
if ('share' in navigator && !account.get('suspended')) {
|
||||
menu.push({ text: intl.formatMessage(messages.share, { name: account.get('username') }), action: this.handleShare });
|
||||
menu.push(null);
|
||||
}
|
||||
|
||||
if (account.get('id') === me) {
|
||||
if (profileLink) menu.push({ text: intl.formatMessage(messages.edit_profile), href: profileLink });
|
||||
if (preferencesLink) menu.push({ text: intl.formatMessage(messages.preferences), href: preferencesLink });
|
||||
|
@ -349,6 +352,7 @@ class Header extends ImmutablePureComponent {
|
|||
<>
|
||||
{actionBtn}
|
||||
{bellBtn}
|
||||
{shareBtn}
|
||||
</>
|
||||
)}
|
||||
|
||||
|
|
|
@ -1240,6 +1240,17 @@ body > [data-popper-placement] {
|
|||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
&.copyable {
|
||||
transition: all 300ms linear;
|
||||
}
|
||||
|
||||
&.copied {
|
||||
border-color: $valid-value-color;
|
||||
color: $valid-value-color;
|
||||
transition: none;
|
||||
background-color: rgba($valid-value-color, 0.15);
|
||||
}
|
||||
}
|
||||
|
||||
.domain__wrapper {
|
||||
|
@ -7965,6 +7976,7 @@ noscript {
|
|||
|
||||
.account__header {
|
||||
overflow: hidden;
|
||||
container: account-header / inline-size;
|
||||
|
||||
&.inactive {
|
||||
opacity: 0.5;
|
||||
|
@ -8061,6 +8073,16 @@ noscript {
|
|||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
&.copied {
|
||||
border-color: $valid-value-color;
|
||||
}
|
||||
}
|
||||
|
||||
@container account-header (max-width: 372px) {
|
||||
.optional {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue