Merge remote-tracking branch 'origin/next' into next-colors
This commit is contained in:
commit
12617bf7de
70 changed files with 171 additions and 165 deletions
|
@ -9,33 +9,6 @@
|
|||
<link href="/manifest.json" rel="manifest">
|
||||
<!--server-generated-meta-->
|
||||
<link rel="icon" type="image/png" href="/favicon.png">
|
||||
<link href='/icons/icon-57x57.png' rel='apple-touch-icon' sizes='57x57'>
|
||||
<link href='/icons/icon-64x64.png' rel='apple-touch-icon' sizes='64x64'>
|
||||
<link href='/icons/icon-72x72.png' rel='apple-touch-icon' sizes='72x72'>
|
||||
<link href='/icons/icon-114x114.png' rel='apple-touch-icon' sizes='114x114'>
|
||||
<link href='/icons/icon-120x120.png' rel='apple-touch-icon' sizes='120x120'>
|
||||
<link href='/icons/icon-180x180.png' rel='apple-touch-icon' sizes='180x180'>
|
||||
<link href='/icons/icon-192x192.png' rel='apple-touch-icon' sizes='192x192'>
|
||||
<link href='/icons/icon-512x512.png' rel='apple-touch-icon' sizes='512x512'>
|
||||
<script>
|
||||
if(window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.didBeginLoadingSoapbox) {
|
||||
window.webkit.messageHandlers.didBeginLoadingSoapbox.postMessage("started");
|
||||
}
|
||||
</script>
|
||||
<!-- Matomo -->
|
||||
<script>
|
||||
var _paq = window._paq = window._paq || [];
|
||||
/* tracker methods like "setCustomDimension" should be called before "trackPageView" */
|
||||
_paq.push(['trackPageView']);
|
||||
_paq.push(['enableLinkTracking']);
|
||||
(function() {
|
||||
var u="//trk.bonsa.net/";
|
||||
_paq.push(['setTrackerUrl', u+'matomo.php']);
|
||||
_paq.push(['setSiteId', '23231245']);
|
||||
var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
|
||||
g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body class="theme-mode-light no-reduce-motion">
|
||||
<div id="soapbox">
|
||||
|
|
|
@ -4,7 +4,7 @@ import { Link } from 'react-router-dom';
|
|||
import HoverRefWrapper from 'soapbox/components/hover_ref_wrapper';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
import ActionButton from 'soapbox/features/ui/components/action_button';
|
||||
import { useAppSelector } from 'soapbox/hooks';
|
||||
import { useAppSelector, useOnScreen } from 'soapbox/hooks';
|
||||
import { getAcct } from 'soapbox/utils/accounts';
|
||||
import { displayFqn } from 'soapbox/utils/state';
|
||||
|
||||
|
@ -52,8 +52,9 @@ const Account = ({
|
|||
timestampUrl,
|
||||
withRelationship = true,
|
||||
}: IAccount) => {
|
||||
const overflowRef = React.useRef(null);
|
||||
const actionRef = React.useRef(null);
|
||||
const overflowRef = React.useRef<HTMLDivElement>(null);
|
||||
const actionRef = React.useRef<HTMLDivElement>(null);
|
||||
const isOnScreen = useOnScreen(overflowRef);
|
||||
|
||||
const [style, setStyle] = React.useState<React.CSSProperties>({ visibility: 'hidden' });
|
||||
|
||||
|
@ -93,18 +94,19 @@ const Account = ({
|
|||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
const style: React.CSSProperties = {};
|
||||
if (isOnScreen) {
|
||||
const style: React.CSSProperties = {};
|
||||
const actionWidth = actionRef.current?.clientWidth;
|
||||
|
||||
const actionWidth = actionRef.current?.clientWidth;
|
||||
if (overflowRef.current) {
|
||||
style.maxWidth = overflowRef.current.clientWidth - 30 - avatarSize - actionWidth;
|
||||
} else {
|
||||
style.visibility = 'hidden';
|
||||
}
|
||||
|
||||
if (overflowRef.current) {
|
||||
style.maxWidth = overflowRef.current.clientWidth - 30 - avatarSize - actionWidth;
|
||||
} else {
|
||||
style.visibility = 'hidden';
|
||||
setStyle(style);
|
||||
}
|
||||
|
||||
setStyle(style);
|
||||
}, [overflowRef, actionRef]);
|
||||
}, [isOnScreen, overflowRef, actionRef]);
|
||||
|
||||
if (!account) {
|
||||
return null;
|
||||
|
@ -161,8 +163,8 @@ const Account = ({
|
|||
</LinkEl>
|
||||
</ProfilePopper>
|
||||
|
||||
<HStack alignItems='center' space={1}>
|
||||
<Text theme='muted' size='sm'>@{username}</Text>
|
||||
<HStack alignItems='center' space={1} style={style}>
|
||||
<Text theme='muted' size='sm' truncate>@{username}</Text>
|
||||
|
||||
{(timestamp) ? (
|
||||
<>
|
||||
|
|
|
@ -8,7 +8,7 @@ import StillImage from 'soapbox/components/still_image';
|
|||
export default class Avatar extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
size: PropTypes.number,
|
||||
style: PropTypes.object,
|
||||
className: PropTypes.string,
|
||||
|
|
|
@ -6,7 +6,7 @@ import StillImage from 'soapbox/components/still_image';
|
|||
export default class AvatarOverlay extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
friend: ImmutablePropTypes.map.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ export default @connect(mapStateToProps)
|
|||
class DisplayName extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
displayFqn: PropTypes.bool,
|
||||
others: ImmutablePropTypes.list,
|
||||
children: PropTypes.node,
|
||||
|
|
|
@ -207,7 +207,7 @@ class Dropdown extends React.PureComponent {
|
|||
pressed: PropTypes.bool,
|
||||
title: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
status: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
isUserTouching: PropTypes.func,
|
||||
isModalOpen: PropTypes.bool.isRequired,
|
||||
onOpen: PropTypes.func.isRequired,
|
||||
|
|
|
@ -17,15 +17,16 @@ export default class Icon extends React.PureComponent {
|
|||
id: PropTypes.string,
|
||||
src: PropTypes.string,
|
||||
className: PropTypes.string,
|
||||
fixedWidth: PropTypes.bool,
|
||||
};
|
||||
|
||||
render() {
|
||||
const { id, src, ...rest } = this.props;
|
||||
const { id, src, fixedWidth, ...rest } = this.props;
|
||||
|
||||
if (src) {
|
||||
return <SvgIcon src={src} {...rest} />;
|
||||
} else {
|
||||
return <ForkAwesomeIcon id={id} {...rest} />;
|
||||
return <ForkAwesomeIcon id={id} fixedWidth={fixedWidth} {...rest} />;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ const shouldLetterbox = attachment => {
|
|||
class Item extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
attachment: ImmutablePropTypes.map.isRequired,
|
||||
attachment: ImmutablePropTypes.record.isRequired,
|
||||
standalone: PropTypes.bool,
|
||||
index: PropTypes.number.isRequired,
|
||||
size: PropTypes.number.isRequired,
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import { withRouter } from 'react-router-dom';
|
||||
|
||||
export default @withRouter
|
||||
class Permalink extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
className: PropTypes.string,
|
||||
href: PropTypes.string.isRequired,
|
||||
to: PropTypes.string.isRequired,
|
||||
children: PropTypes.node,
|
||||
onInterceptClick: PropTypes.func,
|
||||
history: PropTypes.object,
|
||||
};
|
||||
|
||||
handleClick = e => {
|
||||
if (this.props.onInterceptClick && this.props.onInterceptClick()) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.props.history && e.button === 0 && !(e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
this.props.history.push(this.props.to);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { href, children, className, onInterceptClick, ...other } = this.props;
|
||||
|
||||
return (
|
||||
<a target='_blank' href={href} onClick={this.handleClick} {...other} className={`permalink${className ? ' ' + className : ''}`}>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
37
app/soapbox/components/permalink.tsx
Normal file
37
app/soapbox/components/permalink.tsx
Normal file
|
@ -0,0 +1,37 @@
|
|||
import * as React from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
interface IPermaLink extends Pick<React.HTMLAttributes<HTMLAnchorElement>, 'dangerouslySetInnerHTML'> {
|
||||
className?: string,
|
||||
href: string,
|
||||
title?: string,
|
||||
to: string,
|
||||
}
|
||||
|
||||
const Permalink: React.FC<IPermaLink> = (props) => {
|
||||
const history = useHistory();
|
||||
|
||||
const { className, href, title, to, children, ...filteredProps } = props;
|
||||
|
||||
const handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
if (event.button === 0 && !(event.ctrlKey || event.metaKey)) {
|
||||
event.preventDefault();
|
||||
history.push(to);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<a
|
||||
target='_blank'
|
||||
href={href}
|
||||
onClick={handleClick}
|
||||
title={title}
|
||||
className={`permalink${className ? ' ' + className : ''}`}
|
||||
{...filteredProps}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
export default Permalink;
|
|
@ -134,7 +134,7 @@ export const ProfileHoverCard = ({ visible }) => {
|
|||
ProfileHoverCard.propTypes = {
|
||||
visible: PropTypes.bool,
|
||||
accountId: PropTypes.string,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
};
|
||||
|
||||
ProfileHoverCard.defaultProps = {
|
||||
|
|
|
@ -43,7 +43,7 @@ class ScrollableList extends PureComponent {
|
|||
children: PropTypes.node,
|
||||
onScrollToTop: PropTypes.func,
|
||||
onScroll: PropTypes.func,
|
||||
placeholderComponent: PropTypes.func,
|
||||
placeholderComponent: PropTypes.object,
|
||||
placeholderCount: PropTypes.number,
|
||||
autoload: PropTypes.bool,
|
||||
onRefresh: PropTypes.func,
|
||||
|
|
|
@ -55,8 +55,8 @@ export default @injectIntl @withRouter
|
|||
class Status extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
account: ImmutablePropTypes.record,
|
||||
otherAccounts: ImmutablePropTypes.list,
|
||||
onClick: PropTypes.func,
|
||||
onReply: PropTypes.func,
|
||||
|
|
|
@ -69,7 +69,7 @@ const messages = defineMessages({
|
|||
class StatusActionBar extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.record.isRequired,
|
||||
onOpenUnauthorizedModal: PropTypes.func.isRequired,
|
||||
onOpenReblogsModal: PropTypes.func.isRequired,
|
||||
onReply: PropTypes.func,
|
||||
|
|
|
@ -28,7 +28,7 @@ export default @connect(mapStateToProps)
|
|||
class StatusContent extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.record.isRequired,
|
||||
reblogContent: PropTypes.string,
|
||||
expanded: PropTypes.bool,
|
||||
onExpandedToggle: PropTypes.func,
|
||||
|
|
|
@ -223,7 +223,7 @@ export default class StatusList extends ImmutablePureComponent {
|
|||
isLoading={isLoading}
|
||||
showLoading={isLoading && statusIds.size === 0}
|
||||
onLoadMore={onLoadMore && this.handleLoadOlder}
|
||||
placeholderComponent={() => <PlaceholderStatus />}
|
||||
placeholderComponent={PlaceholderStatus}
|
||||
placeholderCount={20}
|
||||
ref={this.setRef}
|
||||
className={divideType === 'border' ? 'divide-y divide-solid divide-gray-200' : 'sm:space-y-3 divide-y divide-solid divide-gray-200 sm:divide-none'}
|
||||
|
|
|
@ -23,7 +23,7 @@ export default @connect(null, mapDispatchToProps)
|
|||
class StatusReplyMentions extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.record.isRequired,
|
||||
onOpenMentionsModal: PropTypes.func,
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ class ThumbNavigation extends React.PureComponent {
|
|||
|
||||
static propTypes = {
|
||||
logo: PropTypes.string,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
dashboardCount: PropTypes.number,
|
||||
notificationCount: PropTypes.number,
|
||||
chatsCount: PropTypes.number,
|
||||
|
|
|
@ -29,6 +29,7 @@ interface IHStack {
|
|||
justifyContent?: 'between' | 'center',
|
||||
space?: 0.5 | 1 | 1.5 | 2 | 3 | 4 | 6,
|
||||
grow?: boolean,
|
||||
style?: React.CSSProperties
|
||||
}
|
||||
|
||||
const HStack: React.FC<IHStack> = (props) => {
|
||||
|
|
|
@ -97,7 +97,7 @@ class SoapboxMount extends React.PureComponent {
|
|||
static propTypes = {
|
||||
showIntroduction: PropTypes.bool,
|
||||
me: SoapboxPropTypes.me,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
instanceLoaded: PropTypes.bool,
|
||||
reduceMotion: PropTypes.bool,
|
||||
underlineLinks: PropTypes.bool,
|
||||
|
|
|
@ -86,8 +86,8 @@ export default @connect(mapStateToProps)
|
|||
class Header extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
meAccount: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
meaccount: ImmutablePropTypes.record,
|
||||
identity_props: ImmutablePropTypes.list,
|
||||
intl: PropTypes.object.isRequired,
|
||||
username: PropTypes.string,
|
||||
|
|
|
@ -12,7 +12,7 @@ export default @withRouter
|
|||
class Header extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
identity_proofs: ImmutablePropTypes.list,
|
||||
onFollow: PropTypes.func.isRequired,
|
||||
onBlock: PropTypes.func.isRequired,
|
||||
|
|
|
@ -22,7 +22,7 @@ export default @connect()
|
|||
class ReportStatus extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.record.isRequired,
|
||||
report: ImmutablePropTypes.map,
|
||||
};
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ class UnapprovedAccount extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
};
|
||||
|
||||
handleApprove = () => {
|
||||
|
|
|
@ -50,7 +50,7 @@ class Dashboard extends ImmutablePureComponent {
|
|||
intl: PropTypes.object.isRequired,
|
||||
instance: ImmutablePropTypes.map.isRequired,
|
||||
supportsEmailList: PropTypes.bool,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
};
|
||||
|
||||
handleSubscribersClick = e => {
|
||||
|
|
|
@ -49,7 +49,7 @@ export default @connect(makeMapStateToProps, mapDispatchToProps)
|
|||
class Account extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
apId: PropTypes.string.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onAdd: PropTypes.func.isRequired,
|
||||
|
|
|
@ -36,7 +36,7 @@ class Account extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
accountId: PropTypes.string.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
|
@ -256,8 +256,6 @@ class PrivacyDropdown extends React.PureComponent {
|
|||
className='text-gray-400 hover:text-gray-600'
|
||||
src={valueOption.icon}
|
||||
title={intl.formatMessage(messages.change_privacy)}
|
||||
expanded={open}
|
||||
active={open}
|
||||
onClick={this.handleToggle}
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onKeyDown={this.handleButtonKeyDown}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { isRtl } from '../../../rtl';
|
|||
export default class ReplyIndicator extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
onCancel: PropTypes.func.isRequired,
|
||||
hideActions: PropTypes.bool,
|
||||
};
|
||||
|
|
|
@ -40,7 +40,7 @@ class CreateApp extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
defaultScopes: PropTypes.string,
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ class AccountCard extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
me: SoapboxPropTypes.me,
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
autoPlayGif: PropTypes.bool,
|
||||
};
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ const ProfilePreview = ({ account, displayFqn }) => (
|
|||
);
|
||||
|
||||
ProfilePreview.propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
displayFqn: PropTypes.bool,
|
||||
};
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ class EditProfile extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
maxFields: PropTypes.number,
|
||||
verifiedCanEditName: PropTypes.bool,
|
||||
};
|
||||
|
|
|
@ -30,7 +30,7 @@ export default @connect(makeMapStateToProps)
|
|||
class Account extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ export default @injectIntl
|
|||
class AccountAuthorize extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
onAuthorize: PropTypes.func.isRequired,
|
||||
onReject: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
|
|
@ -35,7 +35,7 @@ class GroupTimeline extends React.PureComponent {
|
|||
hasUnread: PropTypes.bool,
|
||||
group: PropTypes.oneOfType([ImmutablePropTypes.map, PropTypes.bool]),
|
||||
relationships: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ export default @connect(makeMapStateToProps)
|
|||
class Account extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
|
@ -51,7 +51,7 @@ class ListAdder extends ImmutablePureComponent {
|
|||
onInitialize: PropTypes.func.isRequired,
|
||||
onReset: PropTypes.func.isRequired,
|
||||
listIds: ImmutablePropTypes.list.isRequired,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
|
|
|
@ -37,7 +37,7 @@ export default @connect(makeMapStateToProps, mapDispatchToProps)
|
|||
class Account extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onRemove: PropTypes.func.isRequired,
|
||||
onAdd: PropTypes.func.isRequired,
|
||||
|
|
|
@ -18,7 +18,7 @@ export default @injectIntl
|
|||
class FollowRequest extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
onAuthorize: PropTypes.func.isRequired,
|
||||
onReject: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
|
|
@ -228,7 +228,7 @@ const Notification = (props) => {
|
|||
|
||||
Notification.propTypes = {
|
||||
hidden: PropTypes.bool,
|
||||
notification: ImmutablePropTypes.map.isRequired,
|
||||
notification: ImmutablePropTypes.record.isRequired,
|
||||
onMoveUp: PropTypes.func.isRequired,
|
||||
onMoveDown: PropTypes.func.isRequired,
|
||||
onMention: PropTypes.func.isRequired,
|
||||
|
|
|
@ -11,7 +11,7 @@ import { MediaGallery, Video, Audio } from '../../ui/util/async-components';
|
|||
export default class StatusCheckBox extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.record.isRequired,
|
||||
checked: PropTypes.bool,
|
||||
onToggle: PropTypes.func.isRequired,
|
||||
disabled: PropTypes.bool,
|
||||
|
|
|
@ -48,7 +48,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||
class ScheduledStatusActionBar extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.record.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
me: SoapboxPropTypes.me,
|
||||
onCancelClick: PropTypes.func.isRequired,
|
||||
|
|
|
@ -84,7 +84,7 @@ const mapDispatchToProps = (dispatch, { status }) => ({
|
|||
class ActionBar extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.record.isRequired,
|
||||
onReply: PropTypes.func.isRequired,
|
||||
onReblog: PropTypes.func.isRequired,
|
||||
onQuote: PropTypes.func.isRequired,
|
||||
|
|
|
@ -61,7 +61,7 @@ const addAutoPlay = html => {
|
|||
export default class Card extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
card: ImmutablePropTypes.map,
|
||||
card: ImmutablePropTypes.record,
|
||||
maxDescription: PropTypes.number,
|
||||
onOpenMedia: PropTypes.func.isRequired,
|
||||
compact: PropTypes.bool,
|
||||
|
|
|
@ -27,7 +27,7 @@ export default @injectIntl
|
|||
class DetailedStatus extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
onOpenMedia: PropTypes.func.isRequired,
|
||||
onOpenVideo: PropTypes.func.isRequired,
|
||||
onToggleHidden: PropTypes.func.isRequired,
|
||||
|
|
|
@ -20,7 +20,7 @@ export default @injectIntl @withRouter
|
|||
class QuotedStatus extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
onCancel: PropTypes.func,
|
||||
intl: PropTypes.object.isRequired,
|
||||
compose: PropTypes.bool,
|
||||
|
|
|
@ -55,7 +55,7 @@ export default @connect(mapStateToProps, mapDispatchToProps)
|
|||
class StatusInteractionBar extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
me: SoapboxPropTypes.me,
|
||||
allowedEmoji: ImmutablePropTypes.list,
|
||||
features: PropTypes.object.isRequired,
|
||||
|
|
|
@ -165,7 +165,7 @@ class Status extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
params: PropTypes.object.isRequired,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
status: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
ancestorsIds: ImmutablePropTypes.orderedSet,
|
||||
descendantsIds: ImmutablePropTypes.orderedSet,
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
|
|
@ -68,7 +68,7 @@ export default @connect(mapStateToProps, mapDispatchToProps)
|
|||
class ActionButton extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
onFollow: PropTypes.func.isRequired,
|
||||
onBlock: PropTypes.func.isRequired,
|
||||
onOpenUnauthorizedModal: PropTypes.func.isRequired,
|
||||
|
|
|
@ -74,7 +74,7 @@ const ActionsModal = ({ status, actions, onClick, onClose }) => {
|
|||
};
|
||||
|
||||
ActionsModal.propTypes = {
|
||||
status: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
actions: PropTypes.array,
|
||||
onClick: PropTypes.func,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
|
|
|
@ -18,7 +18,7 @@ export default @injectIntl @withRouter
|
|||
class BoostModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
status: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.record.isRequired,
|
||||
onReblog: PropTypes.func.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
|
|
@ -29,7 +29,7 @@ const mapStateToProps = state => {
|
|||
class ComposeModal extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
intl: PropTypes.object.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
composeText: PropTypes.string,
|
||||
|
|
|
@ -6,10 +6,11 @@ import { connect } from 'react-redux';
|
|||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { logOut } from 'soapbox/actions/auth';
|
||||
import { getSoapboxConfig } from 'soapbox/actions/soapbox';
|
||||
import { Text } from 'soapbox/components/ui';
|
||||
import emojify from 'soapbox/features/emoji/emoji';
|
||||
import { getBaseURL } from 'soapbox/utils/accounts';
|
||||
// import sourceCode from 'soapbox/utils/code';
|
||||
import sourceCode from 'soapbox/utils/code';
|
||||
import { getFeatures } from 'soapbox/utils/features';
|
||||
|
||||
import { openModal } from '../../../actions/modals';
|
||||
|
@ -19,9 +20,11 @@ const mapStateToProps = state => {
|
|||
const account = state.getIn(['accounts', me]);
|
||||
const instance = state.get('instance');
|
||||
const features = getFeatures(instance);
|
||||
const soapboxConfig = getSoapboxConfig(state);
|
||||
|
||||
return {
|
||||
account,
|
||||
soapboxConfig,
|
||||
profileDirectory: features.profileDirectory,
|
||||
federating: features.federating,
|
||||
showAliases: features.accountAliasesAPI,
|
||||
|
@ -41,7 +44,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||
},
|
||||
});
|
||||
|
||||
const LinkFooter = ({ onOpenHotkeys, account, profileDirectory, federating, showAliases, importAPI, onClickLogOut, baseURL }) => (
|
||||
const LinkFooter = ({ onOpenHotkeys, account, profileDirectory, federating, showAliases, importAPI, onClickLogOut, baseURL, soapboxConfig }) => (
|
||||
<div className='space-y-2'>
|
||||
<ul className='flex flex-wrap items-center divide-x-dot'>
|
||||
{account && <>
|
||||
|
@ -68,26 +71,29 @@ const LinkFooter = ({ onOpenHotkeys, account, profileDirectory, federating, show
|
|||
</ul>
|
||||
|
||||
<Text theme='muted' size='sm'>
|
||||
{/*<FormattedMessage
|
||||
id='getting_started.open_source_notice'
|
||||
defaultMessage='{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).'
|
||||
values={{
|
||||
code_name: sourceCode.displayName,
|
||||
code_link: <a href={sourceCode.url} rel='noopener' target='_blank'>{sourceCode.repository}</a>,
|
||||
code_version: sourceCode.version,
|
||||
}}
|
||||
/>*/}
|
||||
<FormattedMessage
|
||||
id='link_footer.made_in_usa'
|
||||
defaultMessage='Proudly made in the United States of America. {emoji}'
|
||||
values={{ emoji: <span className='inline-block align-middle' dangerouslySetInnerHTML={{ __html: emojify('🇺🇸') }} /> }}
|
||||
/>
|
||||
{soapboxConfig.get('linkFooterMessage') ? (
|
||||
<span
|
||||
className='inline-block align-middle'
|
||||
dangerouslySetInnerHTML={{ __html: emojify(soapboxConfig.get('linkFooterMessage')) }}
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id='getting_started.open_source_notice'
|
||||
defaultMessage='{code_name} is open source software. You can contribute or report issues at {code_link} (v{code_version}).'
|
||||
values={{
|
||||
code_name: sourceCode.displayName,
|
||||
code_link: <a href={sourceCode.url} rel='noopener' target='_blank'>{sourceCode.repository}</a>,
|
||||
code_version: sourceCode.version,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
|
||||
LinkFooter.propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
soapboxConfig: ImmutablePropTypes.map,
|
||||
profileDirectory: PropTypes.bool,
|
||||
federating: PropTypes.bool,
|
||||
showAliases: PropTypes.bool,
|
||||
|
|
|
@ -26,8 +26,8 @@ class MediaModal extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
media: ImmutablePropTypes.list.isRequired,
|
||||
status: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
account: ImmutablePropTypes.record,
|
||||
index: PropTypes.number.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
|
|
@ -116,7 +116,7 @@ const ProfileDropdown: React.FC<IProfileDropdown> = ({ account, children }) => {
|
|||
const itemProps = menuItem.action ? { onSelect: menuItem.action } : { to: menuItem.to, as: Link };
|
||||
|
||||
return (
|
||||
<Comp key={idx} {...itemProps}>
|
||||
<Comp key={idx} {...itemProps} className='truncate'>
|
||||
{menuItem.text}
|
||||
</Comp>
|
||||
);
|
||||
|
|
|
@ -37,7 +37,7 @@ const messages = defineMessages({
|
|||
class ProfileInfoPanel extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
identity_proofs: ImmutablePropTypes.list,
|
||||
intl: PropTypes.object.isRequired,
|
||||
username: PropTypes.string,
|
||||
|
|
|
@ -16,7 +16,7 @@ import MediaItem from '../../account_gallery/components/media_item';
|
|||
class ProfileMediaPanel extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
attachments: ImmutablePropTypes.list,
|
||||
dispatch: PropTypes.func.isRequired,
|
||||
};
|
||||
|
|
|
@ -18,7 +18,7 @@ class ProfileStats extends React.PureComponent {
|
|||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
className: PropTypes.string,
|
||||
onClickHandler: PropTypes.func,
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ class ReportModal extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
isSubmitting: PropTypes.bool,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
statusIds: ImmutablePropTypes.orderedSet.isRequired,
|
||||
comment: PropTypes.string.isRequired,
|
||||
forward: PropTypes.bool,
|
||||
|
|
|
@ -49,7 +49,7 @@ export default @connect(mapStateToProps, mapDispatchToProps)
|
|||
class SubscriptionButton extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
features: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import { makeGetAccount } from '../../../selectors';
|
|||
class UserPanel extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
displayFqn: PropTypes.bool,
|
||||
intl: PropTypes.object.isRequired,
|
||||
domain: PropTypes.string,
|
||||
|
|
|
@ -12,8 +12,8 @@ class VideoModal extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
media: ImmutablePropTypes.map.isRequired,
|
||||
status: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.map,
|
||||
status: ImmutablePropTypes.record,
|
||||
account: ImmutablePropTypes.record,
|
||||
time: PropTypes.number,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
history: PropTypes.object,
|
||||
|
|
|
@ -40,7 +40,7 @@ class WelcomeButton extends ImmutablePureComponent {
|
|||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
account: ImmutablePropTypes.map.isRequired,
|
||||
account: ImmutablePropTypes.record.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class WrappedRoute extends React.Component {
|
|||
content: PropTypes.node,
|
||||
componentParams: PropTypes.object,
|
||||
layout: PropTypes.object,
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
settings: ImmutablePropTypes.map.isRequired,
|
||||
publicRoute: PropTypes.bool,
|
||||
staffOnly: PropTypes.bool,
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
export { useAppSelector } from './useAppSelector';
|
||||
export { useOnScreen } from './useOnScreen';
|
||||
|
|
19
app/soapbox/hooks/useOnScreen.ts
Normal file
19
app/soapbox/hooks/useOnScreen.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import * as React from 'react';
|
||||
|
||||
export const useOnScreen = (ref: React.MutableRefObject<HTMLElement>) => {
|
||||
const [isIntersecting, setIntersecting] = React.useState(false);
|
||||
|
||||
const observer = new IntersectionObserver(
|
||||
([entry]) => setIntersecting(entry.isIntersecting),
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
observer.observe(ref.current);
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return isIntersecting;
|
||||
};
|
|
@ -20,7 +20,7 @@ export default @connect(mapStateToProps)
|
|||
class GroupsPage extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
};
|
||||
|
||||
render() {
|
||||
|
|
|
@ -68,7 +68,7 @@ export default @connect(mapStateToProps)
|
|||
class ProfilePage extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
account: ImmutablePropTypes.record,
|
||||
accountUsername: PropTypes.string.isRequired,
|
||||
displayFqn: PropTypes.bool,
|
||||
features: PropTypes.object,
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
}
|
||||
|
||||
.notification-bar-wrapper {
|
||||
@apply p-4 flex items-start;
|
||||
@apply p-4 flex items-center justify-between w-full space-x-2;
|
||||
}
|
||||
|
||||
.notification-bar-title {
|
||||
|
@ -50,3 +50,10 @@
|
|||
.notification-bar-message {
|
||||
@apply text-sm text-gray-700;
|
||||
}
|
||||
|
||||
.notification-bar-action a {
|
||||
@apply inline-flex items-center px-2.5 py-1 border border-solid border-gray-300
|
||||
shadow-sm text-xs font-medium rounded-full text-gray-700 bg-white
|
||||
hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2
|
||||
focus:ring-primary-500;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue