Allow removing deleted quotes from composer (#36080)
This commit is contained in:
parent
872044484c
commit
84d1ba980b
4 changed files with 140 additions and 66 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useEffect, useMemo } from 'react';
|
||||
import { useEffect, useMemo, useRef } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
|
|
@ -13,7 +13,9 @@ import type { RootState } from 'mastodon/store';
|
|||
import { useAppDispatch, useAppSelector } from 'mastodon/store';
|
||||
|
||||
import { fetchStatus } from '../actions/statuses';
|
||||
import { makeGetStatus } from '../selectors';
|
||||
import { makeGetStatusWithExtraInfo } from '../selectors';
|
||||
|
||||
import { Button } from './button';
|
||||
|
||||
const MAX_QUOTE_POSTS_NESTING_LEVEL = 1;
|
||||
|
||||
|
|
@ -55,11 +57,15 @@ const NestedQuoteLink: React.FC<{ status: Status }> = ({ status }) => {
|
|||
);
|
||||
};
|
||||
|
||||
type QuoteMap = ImmutableMap<'state' | 'quoted_status', string | null>;
|
||||
type GetStatusSelector = (
|
||||
state: RootState,
|
||||
props: { id?: string | null; contextType?: string },
|
||||
) => Status | null;
|
||||
) => {
|
||||
status: Status | null;
|
||||
loadingState: 'not-found' | 'loading' | 'filtered' | 'complete';
|
||||
};
|
||||
|
||||
type QuoteMap = ImmutableMap<'state' | 'quoted_status', string | null>;
|
||||
|
||||
interface QuotedStatusProps {
|
||||
quote: QuoteMap;
|
||||
|
|
@ -86,31 +92,41 @@ export const QuotedStatus: React.FC<QuotedStatusProps> = ({
|
|||
);
|
||||
|
||||
const quotedStatusId = quote.get('quoted_status');
|
||||
const status = useAppSelector((state) =>
|
||||
quotedStatusId ? state.statuses.get(quotedStatusId) : undefined,
|
||||
const getStatusSelector = useMemo(
|
||||
() => makeGetStatusWithExtraInfo() as GetStatusSelector,
|
||||
[],
|
||||
);
|
||||
const { status, loadingState } = useAppSelector((state) =>
|
||||
getStatusSelector(state, { id: quotedStatusId, contextType }),
|
||||
);
|
||||
|
||||
const shouldLoadQuote = !status?.get('isLoading') && quoteState !== 'deleted';
|
||||
const shouldFetchQuote =
|
||||
!status?.get('isLoading') &&
|
||||
quoteState !== 'deleted' &&
|
||||
loadingState === 'not-found';
|
||||
const isLoaded = loadingState === 'complete';
|
||||
|
||||
const isFetchingQuoteRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldLoadQuote && quotedStatusId) {
|
||||
if (isLoaded) {
|
||||
isFetchingQuoteRef.current = false;
|
||||
}
|
||||
}, [isLoaded]);
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldFetchQuote && quotedStatusId && !isFetchingQuoteRef.current) {
|
||||
dispatch(
|
||||
fetchStatus(quotedStatusId, {
|
||||
parentQuotePostId,
|
||||
alsoFetchContext: false,
|
||||
}),
|
||||
);
|
||||
isFetchingQuoteRef.current = true;
|
||||
}
|
||||
}, [shouldLoadQuote, quotedStatusId, parentQuotePostId, dispatch]);
|
||||
}, [shouldFetchQuote, quotedStatusId, parentQuotePostId, dispatch]);
|
||||
|
||||
// In order to find out whether the quoted post should be completely hidden
|
||||
// due to a matching filter, we run it through the selector used by `status_container`.
|
||||
// If this returns null even though `status` exists, it's because it's filtered.
|
||||
const getStatus = useMemo(() => makeGetStatus(), []) as GetStatusSelector;
|
||||
const statusWithExtraData = useAppSelector((state) =>
|
||||
getStatus(state, { id: quotedStatusId, contextType }),
|
||||
);
|
||||
const isFilteredAndHidden = status && statusWithExtraData === null;
|
||||
const isFilteredAndHidden = loadingState === 'filtered';
|
||||
|
||||
let quoteError: React.ReactNode = null;
|
||||
|
||||
|
|
@ -154,10 +170,20 @@ export const QuotedStatus: React.FC<QuotedStatusProps> = ({
|
|||
quoteState === 'unauthorized'
|
||||
) {
|
||||
quoteError = (
|
||||
<FormattedMessage
|
||||
id='status.quote_error.not_available'
|
||||
defaultMessage='Post unavailable'
|
||||
/>
|
||||
<>
|
||||
<FormattedMessage
|
||||
id='status.quote_error.not_available'
|
||||
defaultMessage='Post unavailable'
|
||||
/>
|
||||
{contextType === 'composer' && (
|
||||
<Button compact plain onClick={onQuoteCancel}>
|
||||
<FormattedMessage
|
||||
id='status.remove_quote'
|
||||
defaultMessage='Remove'
|
||||
/>
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue