Merge remote-tracking branch 'origin/develop' into renovate/major-react-monorepo
This commit is contained in:
commit
7ac41b1bf1
15 changed files with 65 additions and 39 deletions
|
@ -20,6 +20,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Datepicker: correctly default to the current year.
|
- Datepicker: correctly default to the current year.
|
||||||
- Scheduled posts: fix page crashing on deleting a scheduled post.
|
- Scheduled posts: fix page crashing on deleting a scheduled post.
|
||||||
- Events: don't crash when searching for a location.
|
- Events: don't crash when searching for a location.
|
||||||
|
- Search: fixes an abort error when using the navbar search component.
|
||||||
|
- Posts: fix monospace font in Markdown code blocks.
|
||||||
|
- Modals: fix action buttons overflow
|
||||||
|
- Editing: don't insert edited posts to the top of the feed.
|
||||||
|
|
||||||
## [3.0.0] - 2022-12-25
|
## [3.0.0] - 2022-12-25
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import api from '../api';
|
||||||
import { loadCredentials } from './auth';
|
import { loadCredentials } from './auth';
|
||||||
import { importFetchedAccount } from './importer';
|
import { importFetchedAccount } from './importer';
|
||||||
|
|
||||||
import type { AxiosError, AxiosRequestHeaders } from 'axios';
|
import type { AxiosError, RawAxiosRequestHeaders } from 'axios';
|
||||||
import type { AppDispatch, RootState } from 'soapbox/store';
|
import type { AppDispatch, RootState } from 'soapbox/store';
|
||||||
import type { APIEntity } from 'soapbox/types/entities';
|
import type { APIEntity } from 'soapbox/types/entities';
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ const patchMe = (params: Record<string, any>, isFormData = false) =>
|
||||||
(dispatch: AppDispatch, getState: () => RootState) => {
|
(dispatch: AppDispatch, getState: () => RootState) => {
|
||||||
dispatch(patchMeRequest());
|
dispatch(patchMeRequest());
|
||||||
|
|
||||||
const headers: AxiosRequestHeaders = isFormData ? {
|
const headers: RawAxiosRequestHeaders = isFormData ? {
|
||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
} : {};
|
} : {};
|
||||||
|
|
||||||
|
|
|
@ -68,7 +68,7 @@ const createStatus = (params: Record<string, any>, idempotencyKey: string, statu
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(importFetchedStatus(status, idempotencyKey));
|
dispatch(importFetchedStatus(status, idempotencyKey));
|
||||||
dispatch({ type: STATUS_CREATE_SUCCESS, status, params, idempotencyKey });
|
dispatch({ type: STATUS_CREATE_SUCCESS, status, params, idempotencyKey, editing: !!statusId });
|
||||||
|
|
||||||
// Poll the backend for the updated card
|
// Poll the backend for the updated card
|
||||||
if (status.expectsCard) {
|
if (status.expectsCard) {
|
||||||
|
|
|
@ -44,7 +44,7 @@ const AutosuggestAccountInput: React.FC<IAutosuggestAccountInput> = ({
|
||||||
setAccountIds(ImmutableOrderedSet());
|
setAccountIds(ImmutableOrderedSet());
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAccountSearch = useCallback(throttle(q => {
|
const handleAccountSearch = useCallback(throttle((q) => {
|
||||||
const params = { q, limit, resolve: false };
|
const params = { q, limit, resolve: false };
|
||||||
|
|
||||||
dispatch(accountSearch(params, controller.current.signal))
|
dispatch(accountSearch(params, controller.current.signal))
|
||||||
|
@ -53,7 +53,7 @@ const AutosuggestAccountInput: React.FC<IAutosuggestAccountInput> = ({
|
||||||
setAccountIds(ImmutableOrderedSet(accountIds));
|
setAccountIds(ImmutableOrderedSet(accountIds));
|
||||||
})
|
})
|
||||||
.catch(noOp);
|
.catch(noOp);
|
||||||
}, 900, { leading: false, trailing: true }), [limit]);
|
}, 900, { leading: true, trailing: true }), [limit]);
|
||||||
|
|
||||||
const handleChange: React.ChangeEventHandler<HTMLInputElement> = e => {
|
const handleChange: React.ChangeEventHandler<HTMLInputElement> = e => {
|
||||||
refreshCancelToken();
|
refreshCancelToken();
|
||||||
|
|
|
@ -98,13 +98,21 @@ const FeedCarousel = () => {
|
||||||
const [pinnedAvatar, setPinnedAvatar] = useState<Avatar | null>(null);
|
const [pinnedAvatar, setPinnedAvatar] = useState<Avatar | null>(null);
|
||||||
|
|
||||||
const avatarsToList = useMemo(() => {
|
const avatarsToList = useMemo(() => {
|
||||||
const list = avatars.filter((avatar) => avatar.account_id !== pinnedAvatar?.account_id);
|
let list: (Avatar | null)[] = avatars.filter((avatar) => avatar.account_id !== pinnedAvatar?.account_id);
|
||||||
|
|
||||||
|
// If we have an Avatar pinned, let's create a new array with "null"
|
||||||
|
// in the first position of each page.
|
||||||
if (pinnedAvatar) {
|
if (pinnedAvatar) {
|
||||||
return [null, ...list];
|
const index = (currentPage - 1) * pageSize;
|
||||||
|
list = [
|
||||||
|
...list.slice(0, index),
|
||||||
|
null,
|
||||||
|
...list.slice(index),
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
return list;
|
return list;
|
||||||
}, [avatars, pinnedAvatar]);
|
}, [avatars, pinnedAvatar, currentPage, pageSize]);
|
||||||
|
|
||||||
const numberOfPages = Math.ceil(avatars.length / pageSize);
|
const numberOfPages = Math.ceil(avatars.length / pageSize);
|
||||||
const widthPerAvatar = width / (Math.floor(width / 80));
|
const widthPerAvatar = width / (Math.floor(width / 80));
|
||||||
|
|
|
@ -28,6 +28,7 @@ const BirthdaysModal = ({ onClose }: IBirthdaysModal) => {
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='birthdays'
|
scrollKey='birthdays'
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
|
className='max-w-full'
|
||||||
itemClassName='pb-3'
|
itemClassName='pb-3'
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{accountIds.map(id =>
|
||||||
|
|
|
@ -2,7 +2,8 @@ import React, { useEffect } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { fetchEventParticipations } from 'soapbox/actions/events';
|
import { fetchEventParticipations } from 'soapbox/actions/events';
|
||||||
import { Modal, Spinner, Stack } from 'soapbox/components/ui';
|
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||||
|
import { Modal, Spinner } from 'soapbox/components/ui';
|
||||||
import AccountContainer from 'soapbox/containers/account-container';
|
import AccountContainer from 'soapbox/containers/account-container';
|
||||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
@ -33,16 +34,19 @@ const EventParticipantsModal: React.FC<IEventParticipantsModal> = ({ onClose, st
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
body = <Spinner />;
|
body = <Spinner />;
|
||||||
} else {
|
} else {
|
||||||
|
const emptyMessage = <FormattedMessage id='empty_column.event_participants' defaultMessage='No one joined this event yet. When someone does, they will show up here.' />;
|
||||||
|
|
||||||
body = (
|
body = (
|
||||||
<Stack space={3}>
|
<ScrollableList
|
||||||
{accountIds.size > 0 ? (
|
scrollKey='event_participations'
|
||||||
accountIds.map((id) =>
|
emptyMessage={emptyMessage}
|
||||||
|
className='max-w-full'
|
||||||
|
itemClassName='pb-3'
|
||||||
|
>
|
||||||
|
{accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} />,
|
<AccountContainer key={id} id={id} />,
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<FormattedMessage id='empty_column.event_participants' defaultMessage='No one joined this event yet. When someone does, they will show up here.' />
|
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</ScrollableList>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,8 @@ import React, { useEffect } from 'react';
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { fetchFavourites } from 'soapbox/actions/interactions';
|
import { fetchFavourites } from 'soapbox/actions/interactions';
|
||||||
import { Modal, Spinner, Stack } from 'soapbox/components/ui';
|
import ScrollableList from 'soapbox/components/scrollable-list';
|
||||||
|
import { Modal, Spinner } from 'soapbox/components/ui';
|
||||||
import AccountContainer from 'soapbox/containers/account-container';
|
import AccountContainer from 'soapbox/containers/account-container';
|
||||||
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
|
||||||
|
|
||||||
|
@ -33,16 +34,19 @@ const FavouritesModal: React.FC<IFavouritesModal> = ({ onClose, statusId }) => {
|
||||||
if (!accountIds) {
|
if (!accountIds) {
|
||||||
body = <Spinner />;
|
body = <Spinner />;
|
||||||
} else {
|
} else {
|
||||||
|
const emptyMessage = <FormattedMessage id='empty_column.favourites' defaultMessage='No one has liked this post yet. When someone does, they will show up here.' />;
|
||||||
|
|
||||||
body = (
|
body = (
|
||||||
<Stack space={3}>
|
<ScrollableList
|
||||||
{accountIds.size > 0 ? (
|
scrollKey='favourites'
|
||||||
accountIds.map((id) =>
|
emptyMessage={emptyMessage}
|
||||||
|
className='max-w-full'
|
||||||
|
itemClassName='pb-3'
|
||||||
|
>
|
||||||
|
{accountIds.map(id =>
|
||||||
<AccountContainer key={id} id={id} />,
|
<AccountContainer key={id} id={id} />,
|
||||||
)
|
|
||||||
) : (
|
|
||||||
<FormattedMessage id='empty_column.favourites' defaultMessage='No one has liked this post yet. When someone does, they will show up here.' />
|
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</ScrollableList>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ const MentionsModal: React.FC<IMentionsModal> = ({ onClose, statusId }) => {
|
||||||
body = (
|
body = (
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='mentions'
|
scrollKey='mentions'
|
||||||
|
className='max-w-full'
|
||||||
itemClassName='pb-3'
|
itemClassName='pb-3'
|
||||||
>
|
>
|
||||||
{accountIds.map(id =>
|
{accountIds.map(id =>
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import classNames from 'clsx';
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
|
||||||
|
@ -84,7 +85,9 @@ const ReactionsModal: React.FC<IReactionsModal> = ({ onClose, statusId, reaction
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='reactions'
|
scrollKey='reactions'
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
className='mt-4'
|
className={classNames('max-w-full', {
|
||||||
|
'mt-4': reactions.size > 0,
|
||||||
|
})}
|
||||||
itemClassName='pb-3'
|
itemClassName='pb-3'
|
||||||
>
|
>
|
||||||
{accounts.map((account) =>
|
{accounts.map((account) =>
|
||||||
|
|
|
@ -41,6 +41,7 @@ const ReblogsModal: React.FC<IReblogsModal> = ({ onClose, statusId }) => {
|
||||||
<ScrollableList
|
<ScrollableList
|
||||||
scrollKey='reblogs'
|
scrollKey='reblogs'
|
||||||
emptyMessage={emptyMessage}
|
emptyMessage={emptyMessage}
|
||||||
|
className='max-w-full'
|
||||||
itemClassName='pb-3'
|
itemClassName='pb-3'
|
||||||
>
|
>
|
||||||
{accountIds.map((id) =>
|
{accountIds.map((id) =>
|
||||||
|
|
|
@ -314,7 +314,7 @@ export default function timelines(state: State = initialState, action: AnyAction
|
||||||
if (action.params.scheduled_at) return state;
|
if (action.params.scheduled_at) return state;
|
||||||
return importPendingStatus(state, action.params, action.idempotencyKey);
|
return importPendingStatus(state, action.params, action.idempotencyKey);
|
||||||
case STATUS_CREATE_SUCCESS:
|
case STATUS_CREATE_SUCCESS:
|
||||||
if (action.status.scheduled_at) return state;
|
if (action.status.scheduled_at || action.editing) return state;
|
||||||
return importStatus(state, action.status, action.idempotencyKey);
|
return importStatus(state, action.status, action.idempotencyKey);
|
||||||
case TIMELINE_EXPAND_REQUEST:
|
case TIMELINE_EXPAND_REQUEST:
|
||||||
return setLoading(state, action.timeline, true);
|
return setLoading(state, action.timeline, true);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
@import '~@fontsource/inter/600.css';
|
@import '~@fontsource/inter/600.css';
|
||||||
@import '~@fontsource/inter/700.css';
|
@import '~@fontsource/inter/700.css';
|
||||||
@import '~@fontsource/inter/900.css';
|
@import '~@fontsource/inter/900.css';
|
||||||
|
@import '~@fontsource/roboto-mono/400.css';
|
||||||
|
|
||||||
@import 'mixins';
|
@import 'mixins';
|
||||||
@import 'themes';
|
@import 'themes';
|
||||||
|
@ -16,7 +17,6 @@
|
||||||
@import 'accounts';
|
@import 'accounts';
|
||||||
@import 'loading';
|
@import 'loading';
|
||||||
@import 'ui';
|
@import 'ui';
|
||||||
// @import 'introduction';
|
|
||||||
@import 'emoji-picker';
|
@import 'emoji-picker';
|
||||||
@import 'rtl';
|
@import 'rtl';
|
||||||
@import 'accessibility';
|
@import 'accessibility';
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
"@babel/preset-typescript": "^7.17.12",
|
"@babel/preset-typescript": "^7.17.12",
|
||||||
"@babel/runtime": "^7.18.3",
|
"@babel/runtime": "^7.18.3",
|
||||||
"@fontsource/inter": "^4.5.1",
|
"@fontsource/inter": "^4.5.1",
|
||||||
"@fontsource/roboto": "^4.5.0",
|
"@fontsource/roboto-mono": "^4.5.8",
|
||||||
"@gamestdio/websocket": "^0.3.2",
|
"@gamestdio/websocket": "^0.3.2",
|
||||||
"@jest/globals": "^29.0.0",
|
"@jest/globals": "^29.0.0",
|
||||||
"@lcdp/offline-plugin": "^5.1.0",
|
"@lcdp/offline-plugin": "^5.1.0",
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
"@types/webpack-deadcode-plugin": "^0.1.2",
|
"@types/webpack-deadcode-plugin": "^0.1.2",
|
||||||
"array-includes": "^3.1.5",
|
"array-includes": "^3.1.5",
|
||||||
"autoprefixer": "^10.4.2",
|
"autoprefixer": "^10.4.2",
|
||||||
"axios": "^1.0.0-alpha.1",
|
"axios": "^1.2.2",
|
||||||
"axios-mock-adapter": "^1.21.1",
|
"axios-mock-adapter": "^1.21.1",
|
||||||
"babel-loader": "^8.2.5",
|
"babel-loader": "^8.2.5",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -1404,10 +1404,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-4.5.1.tgz#058d8a02354f3c78e369d452c15d33557ec1b705"
|
resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-4.5.1.tgz#058d8a02354f3c78e369d452c15d33557ec1b705"
|
||||||
integrity sha512-mvtOvXNNVLlF1p/UbLgLrmz2RCOl6Ow+TqyiK10SosoLKX7edsXYiHFHb7XIZdjII6F2sJVPPsJXWhBnbXT2DQ==
|
integrity sha512-mvtOvXNNVLlF1p/UbLgLrmz2RCOl6Ow+TqyiK10SosoLKX7edsXYiHFHb7XIZdjII6F2sJVPPsJXWhBnbXT2DQ==
|
||||||
|
|
||||||
"@fontsource/roboto@^4.5.0":
|
"@fontsource/roboto-mono@^4.5.8":
|
||||||
version "4.5.0"
|
version "4.5.8"
|
||||||
resolved "https://registry.yarnpkg.com/@fontsource/roboto/-/roboto-4.5.0.tgz#d6f925668ba6af46707f1040c43aff498ba204bb"
|
resolved "https://registry.yarnpkg.com/@fontsource/roboto-mono/-/roboto-mono-4.5.8.tgz#f3a48195528b10e154c98365671de14e27605bdb"
|
||||||
integrity sha512-ja4XYw/9kNRFM5Ndk9vwzHWsdBMXczyBazFkTXJQ74QQBnT0BbSsHn0pF60AU0Iznig1Wt9x3rADfG8LANvMpw==
|
integrity sha512-AW44UkbQD0w1CT5mzDbsvhGZ6/bb0YmZzoELj6Sx8vcVEzcbYGUdt2Dtl5zqlOuYMWQFY1mniwWyVv+Bm/lVxw==
|
||||||
|
|
||||||
"@formatjs/ecma402-abstract@1.11.4":
|
"@formatjs/ecma402-abstract@1.11.4":
|
||||||
version "1.11.4"
|
version "1.11.4"
|
||||||
|
@ -3658,10 +3658,10 @@ axios-mock-adapter@^1.21.1:
|
||||||
fast-deep-equal "^3.1.3"
|
fast-deep-equal "^3.1.3"
|
||||||
is-buffer "^2.0.5"
|
is-buffer "^2.0.5"
|
||||||
|
|
||||||
axios@^1.0.0-alpha.1:
|
axios@^1.2.2:
|
||||||
version "1.0.0-alpha.1"
|
version "1.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/axios/-/axios-1.0.0-alpha.1.tgz#ce69c17ca7605d01787ca754dd906e6fccdf71ee"
|
resolved "https://registry.yarnpkg.com/axios/-/axios-1.2.2.tgz#72681724c6e6a43a9fea860fc558127dbe32f9f1"
|
||||||
integrity sha512-p+meG161943WT+K7sJYquHR46xxi/z0tk7vnSmEf/LrfEAyiP+0uTMMYk1OEo1IRF18oGRhnFxN1y8fLcXaTMw==
|
integrity sha512-bz/J4gS2S3I7mpN/YZfGFTqhXTYzRho8Ay38w2otuuDR322KzFIWm/4W2K6gIwvWaws5n+mnb7D1lN9uD+QH6Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects "^1.15.0"
|
follow-redirects "^1.15.0"
|
||||||
form-data "^4.0.0"
|
form-data "^4.0.0"
|
||||||
|
|
Loading…
Reference in a new issue