Merge remote-tracking branch 'soapbox/develop' into events-

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
environments/review-events-5jp5it/deployments/1372
marcin mikołajczak 2 years ago
commit df39036129

@ -0,0 +1,34 @@
.git
/node_modules/
/tmp/
/build/
/coverage/
/.coverage/
/.eslintcache
/.env
/deploy.sh
/.vs/
yarn-error.log*
/junit.xml
/static/
/static-test/
/public/
/dist/
.idea
.DS_Store
# Custom build files
/custom/**/*
!/custom/*
/custom/*.*
!/custom/.gitkeep
!/custom/**/.gitkeep
# surge.sh
/CNAME
/AUTH
/CORS
/ROUTER

@ -142,3 +142,17 @@ pages:
only:
refs:
- develop
docker:
stage: deploy
image: docker:20.10.17
services:
- docker:20.10.17-dind
# https://medium.com/devops-with-valentine/how-to-build-a-docker-image-and-push-it-to-the-gitlab-container-registry-from-a-gitlab-ci-pipeline-acac0d1f26df
script:
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER $CI_REGISTRY --password-stdin
- docker build -t $CI_REGISTRY_IMAGE .
- docker push $CI_REGISTRY_IMAGE
only:
refs:
- develop

@ -1,6 +1,5 @@
{
"recommendations": [
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint",
"bradlc.vscode-tailwindcss",
"stylelint.vscode-stylelint",

@ -0,0 +1,9 @@
{
"editor.insertSpaces": true,
"editor.tabSize": 2,
"files.associations": {
"*.conf.template": "properties"
},
"files.eol": "\n",
"files.insertFinalNewline": false
}

@ -1,5 +1,5 @@
{
// Place your soapbox-fe workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// Place your Soapbox workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:

@ -211,7 +211,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Initial beta release.
[Unreleased]: https://gitlab.com/soapbox-pub/soapbox-fe/-/compare/v1.0.0...develop
[Unreleased patch]: https://gitlab.com/soapbox-pub/soapbox-fe/-/compare/v1.0.0...stable/1.0.x
[1.0.0]: https://gitlab.com/soapbox-pub/soapbox-fe/-/compare/v0.9.0...v1.0.0
[0.9.0]: https://gitlab.com/soapbox-pub/soapbox-fe/-/tags/v0.9.0
[Unreleased]: https://gitlab.com/soapbox-pub/soapbox/-/compare/v1.0.0...develop
[Unreleased patch]: https://gitlab.com/soapbox-pub/soapbox/-/compare/v1.0.0...stable/1.0.x
[1.0.0]: https://gitlab.com/soapbox-pub/soapbox/-/compare/v0.9.0...v1.0.0
[0.9.0]: https://gitlab.com/soapbox-pub/soapbox/-/tags/v0.9.0

@ -0,0 +1,17 @@
FROM node:18 as build
WORKDIR /app
COPY package.json .
COPY yarn.lock .
RUN yarn
COPY . .
ARG NODE_ENV=production
RUN yarn build
FROM nginx:stable-alpine
EXPOSE 5000
ENV PORT=5000
ENV FALLBACK_PORT=4444
ENV BACKEND_URL=http://localhost:4444
ENV CSP=
COPY installation/docker.conf.template /etc/nginx/templates/default.conf.template
COPY --from=build /app/static /usr/share/nginx/html

@ -14,13 +14,13 @@ Installing Soapbox on an existing Pleroma server is extremely easy.
Just ssh into the server and download a .zip of the latest build:
```sh
curl -L https://gitlab.com/soapbox-pub/soapbox-fe/-/jobs/artifacts/develop/download?job=build-production -o soapbox-fe.zip
curl -L https://gitlab.com/soapbox-pub/soapbox/-/jobs/artifacts/develop/download?job=build-production -o soapbox.zip
```
Then unpack it into Pleroma's `instance` directory:
```sh
busybox unzip soapbox-fe.zip -o -d /opt/pleroma/instance
busybox unzip soapbox.zip -o -d /opt/pleroma/instance
```
**That's it!** :tada:
@ -54,7 +54,7 @@ location / {
}
```
(See [`mastodon.conf`](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/installation/mastodon.conf) for a full example.)
(See [`mastodon.conf`](https://gitlab.com/soapbox-pub/soapbox/-/blob/develop/installation/mastodon.conf) for a full example.)
Soapbox incorporates much of the [Mastodon API](https://docs.joinmastodon.org/methods/), [Pleroma API](https://api.pleroma.social/), and more.
It detects features supported by the backend to provide the right experience for the backend.
@ -64,8 +64,8 @@ It detects features supported by the backend to provide the right experience for
To get it running, just clone the repo:
```sh
git clone https://gitlab.com/soapbox-pub/soapbox-fe.git
cd soapbox-fe
git clone https://gitlab.com/soapbox-pub/soapbox.git
cd soapbox
```
Ensure that Node.js and Yarn are installed, then install dependencies:
@ -101,7 +101,7 @@ Try again.
### Troubleshooting: it's not working!
Run `node -V` and compare your Node.js version with the version in [`.tool-versions`](https://gitlab.com/soapbox-pub/soapbox-fe/-/blob/develop/.tool-versions).
Run `node -V` and compare your Node.js version with the version in [`.tool-versions`](https://gitlab.com/soapbox-pub/soapbox/-/blob/develop/.tool-versions).
If they don't match, try installing [asdf](https://asdf-vm.com/).
## Local Dev Configuration

@ -0,0 +1,7 @@
{
"name": "Soapbox",
"description": "Software for the next generation of social media.",
"keywords": ["fediverse"],
"website": "https://soapbox.pub",
"stack": "container"
}

@ -23,6 +23,5 @@
</ol>
<h1 id="opensource">Open Source Software</h1>
<p>Soapbox is free and open source (FOSS) software that runs atop a Pleroma server</p>
<p>The Soapbox repository can be found at <a href="https://gitlab.com/soapbox-pub/soapbox-fe">Soapbox-fe</a></p>
<p>The Pleroma server repository can be found at <a href="https://git.pleroma.social/pleroma/pleroma">Pleroma-be</a></p>
<p>Soapbox is free and open source (FOSS) software.</p>
<p>The Soapbox repository can be found at <a href="https://gitlab.com/soapbox-pub/soapbox">Soapbox</a></p>

@ -106,10 +106,10 @@ export function importFetchedStatus(status: APIEntity, idempotencyKey?: string)
const isBroken = (status: APIEntity) => {
try {
// Skip empty accounts
// https://gitlab.com/soapbox-pub/soapbox-fe/-/issues/424
// https://gitlab.com/soapbox-pub/soapbox/-/issues/424
if (!status.account.id) return true;
// Skip broken reposts
// https://gitlab.com/soapbox-pub/soapbox/-/issues/28
// https://gitlab.com/soapbox-pub/rebased/-/issues/28
if (status.reblog && !status.reblog.account.id) return true;
return false;
} catch (e) {

@ -101,7 +101,7 @@ const editStatus = (id: string) => (dispatch: AppDispatch, getState: () => RootS
api(getState).get(`/api/v1/statuses/${id}/source`).then(response => {
dispatch({ type: STATUS_FETCH_SOURCE_SUCCESS });
dispatch(setComposeToStatus(status, response.data.text, response.data.spoiler_text, false));
dispatch(setComposeToStatus(status, response.data.text, response.data.spoiler_text, response.data.content_type, false));
dispatch(openModal('COMPOSE'));
}).catch(error => {
dispatch({ type: STATUS_FETCH_SOURCE_FAIL, error });

@ -8,7 +8,7 @@ import { useAppSelector, useOnScreen } from 'soapbox/hooks';
import { getAcct } from 'soapbox/utils/accounts';
import { displayFqn } from 'soapbox/utils/state';
import RelativeTimestamp from './relative_timestamp';
import RelativeTimestamp from './relative-timestamp';
import { Avatar, Emoji, HStack, Icon, IconButton, Stack, Text } from './ui';
import type { Account as AccountEntity } from 'soapbox/types/entities';
@ -54,7 +54,7 @@ interface IAccount {
id?: string,
onActionClick?: (account: any) => void,
showProfileHoverCard?: boolean,
timestamp?: string | Date,
timestamp?: string,
timestampUrl?: string,
futureTimestamp?: boolean,
withAccountNote?: boolean,

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState } from 'react';
import AnimatedNumber from 'soapbox/components/animated-number';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { TransitionMotion, spring } from 'react-motion';

@ -1,5 +1,5 @@
import Portal from '@reach/portal';
import classNames from 'classnames';
import classNames from 'clsx';
import { List as ImmutableList } from 'immutable';
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';

@ -1,5 +1,5 @@
import Portal from '@reach/portal';
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import ImmutablePureComponent from 'react-immutable-pure-component';
import Textarea from 'react-textarea-autosize';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import StillImage from 'soapbox/components/still_image';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
interface IBadge {

@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import React from 'react';
import { withRouter } from 'react-router-dom';
// import classNames from 'classnames';
// import classNames from 'clsx';
// import { injectIntl, defineMessages } from 'react-intl';
// import Icon from 'soapbox/components/icon';
import SubNavigation from 'soapbox/components/sub_navigation';

@ -6,7 +6,7 @@ import { useSoapboxConfig } from 'soapbox/hooks';
import { getAcct } from '../utils/accounts';
import Icon from './icon';
import RelativeTimestamp from './relative_timestamp';
import RelativeTimestamp from './relative-timestamp';
import VerificationBadge from './verification_badge';
import type { Account } from 'soapbox/types/entities';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import { supportsPassiveEvents } from 'detect-passive-events';
import React from 'react';
import { spring } from 'react-motion';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState, useEffect, useRef } from 'react';
import { usePopper } from 'react-popper';
import { useDispatch } from 'react-redux';

@ -1,4 +1,4 @@
// import classNames from 'classnames';
// import classNames from 'clsx';
import React from 'react';
import { HotKeys } from 'react-hotkeys';
import ImmutablePureComponent from 'react-immutable-pure-component';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import debounce from 'lodash/debounce';
import PropTypes from 'prop-types';
import React from 'react';

@ -5,7 +5,7 @@
* @see soapbox/components/icon
*/
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
export interface IForkAwesomeIcon extends React.HTMLAttributes<HTMLLIElement> {

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState } from 'react';
import { FormattedMessage } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import debounce from 'lodash/debounce';
import React, { useRef } from 'react';
import { useDispatch } from 'react-redux';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import debounce from 'lodash/debounce';
import React, { useRef } from 'react';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import PropTypes from 'prop-types';
import React from 'react';
import spring from 'react-motion/lib/spring';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import * as React from 'react';
import { v4 as uuidv4 } from 'uuid';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
import throttle from 'lodash/throttle';
import React, { useCallback, useEffect, useRef, useState } from 'react';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import { Map as ImmutableMap, is } from 'immutable';
import PropTypes from 'prop-types';
import React from 'react';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import { createBrowserHistory } from 'history';
import PropTypes from 'prop-types';
import React from 'react';
@ -14,13 +14,11 @@ const messages = defineMessages({
confirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
});
const checkComposeContent = compose => {
export const checkComposeContent = compose => {
return [
compose.text.length > 0,
compose.spoiler_text.length > 0,
compose.media_attachments.size > 0,
compose.in_reply_to !== null,
compose.quote !== null,
compose.poll !== null,
].some(check => check === true);
};

@ -4,7 +4,7 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { fetchPoll, vote } from 'soapbox/actions/polls';
import { useAppDispatch } from 'soapbox/hooks';
import RelativeTimestamp from '../relative_timestamp';
import RelativeTimestamp from '../relative-timestamp';
import { Button, HStack, Stack, Text, Tooltip } from '../ui';
import type { Selected } from './poll';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { Motion, presets, spring } from 'react-motion';

@ -18,7 +18,7 @@ interface IPoll {
}
const messages = defineMessages({
multiple: { id: 'poll.chooseMultiple', defaultMessage: 'Choose as many as you\'d like.' },
multiple: { id: 'poll.choose_multiple', defaultMessage: 'Choose as many as you\'d like.' },
});
const Poll: React.FC<IPoll> = ({ id, status }): JSX.Element | null => {

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useEffect, useState } from 'react';
import { FormattedMessage } from 'react-intl';
import { usePopper } from 'react-popper';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
interface IProgressCircle {

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState } from 'react';
import { defineMessages, useIntl, FormattedMessage, FormattedList } from 'react-intl';
import { useHistory } from 'react-router-dom';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
interface IRadioButton {

@ -1,8 +1,7 @@
import PropTypes from 'prop-types';
import React from 'react';
import { injectIntl, defineMessages } from 'react-intl';
import { injectIntl, defineMessages, IntlShape, FormatDateOptions } from 'react-intl';
import { Text } from './ui';
import Text, { IText } from './ui/text/text';
const messages = defineMessages({
just_now: { id: 'relative_time.just_now', defaultMessage: 'now' },
@ -17,7 +16,7 @@ const messages = defineMessages({
days_remaining: { id: 'time_remaining.days', defaultMessage: '{number, plural, one {# day} other {# days}} left' },
});
const dateFormatOptions = {
const dateFormatOptions: FormatDateOptions = {
hour12: false,
year: 'numeric',
month: 'short',
@ -26,7 +25,7 @@ const dateFormatOptions = {
minute: '2-digit',
};
const shortDateFormatOptions = {
const shortDateFormatOptions: FormatDateOptions = {
month: 'short',
day: 'numeric',
};
@ -38,7 +37,7 @@ const DAY = 1000 * 60 * 60 * 24;
const MAX_DELAY = 2147483647;
const selectUnits = delta => {
const selectUnits = (delta: number) => {
const absDelta = Math.abs(delta);
if (absDelta < MINUTE) {
@ -52,7 +51,7 @@ const selectUnits = delta => {
return 'day';
};
const getUnitDelay = units => {
const getUnitDelay = (units: string) => {
switch (units) {
case 'second':
return SECOND;
@ -67,7 +66,7 @@ const getUnitDelay = units => {
}
};
export const timeAgoString = (intl, date, now, year) => {
export const timeAgoString = (intl: IntlShape, date: Date, now: number, year: number) => {
const delta = now - date.getTime();
let relativeTime;
@ -93,7 +92,7 @@ export const timeAgoString = (intl, date, now, year) => {
return relativeTime;
};
const timeRemainingString = (intl, date, now) => {
const timeRemainingString = (intl: IntlShape, date: Date, now: number) => {
const delta = date.getTime() - now;
let relativeTime;
@ -113,16 +112,21 @@ const timeRemainingString = (intl, date, now) => {
return relativeTime;
};
export default @injectIntl
class RelativeTimestamp extends React.Component {
interface RelativeTimestampProps extends IText {
intl: IntlShape,
timestamp: string,
year?: number,
futureDate?: boolean,
}
static propTypes = {
intl: PropTypes.object.isRequired,
timestamp: PropTypes.string.isRequired,
year: PropTypes.number.isRequired,
theme: PropTypes.string,
futureDate: PropTypes.bool,
};
interface RelativeTimestampState {
now: number,
}
/** Displays a timestamp compared to the current time, eg "1m" for one minute ago. */
class RelativeTimestamp extends React.Component<RelativeTimestampProps, RelativeTimestampState> {
_timer: NodeJS.Timeout | undefined;
state = {
now: Date.now(),
@ -130,10 +134,10 @@ class RelativeTimestamp extends React.Component {
static defaultProps = {
year: (new Date()).getFullYear(),
theme: 'inherit',
theme: 'inherit' as const,
};
shouldComponentUpdate(nextProps, nextState) {
shouldComponentUpdate(nextProps: RelativeTimestampProps, nextState: RelativeTimestampState) {
// As of right now the locale doesn't change without a new page load,
// but we might as well check in case that ever changes.
return this.props.timestamp !== nextProps.timestamp ||
@ -141,14 +145,14 @@ class RelativeTimestamp extends React.Component {
this.state.now !== nextState.now;
}
UNSAFE_componentWillReceiveProps(prevProps) {
UNSAFE_componentWillReceiveProps(prevProps: RelativeTimestampProps) {
if (this.props.timestamp !== prevProps.timestamp) {
this.setState({ now: Date.now() });
}
}
componentDidMount() {
this._scheduleNextUpdate(this.props, this.state);
this._scheduleNextUpdate();
}
UNSAFE_componentWillUpdate() {
@ -156,11 +160,15 @@ class RelativeTimestamp extends React.Component {
}
componentWillUnmount() {
clearTimeout(this._timer);
if (this._timer) {
clearTimeout(this._timer);
}
}
_scheduleNextUpdate() {
clearTimeout(this._timer);
if (this._timer) {
clearTimeout(this._timer);
}
const { timestamp } = this.props;
const delta = (new Date(timestamp)).getTime() - this.state.now;
@ -177,8 +185,8 @@ class RelativeTimestamp extends React.Component {
render() {
const { timestamp, intl, year, futureDate, theme, ...textProps } = this.props;
const date = new Date(timestamp);
const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now) : timeAgoString(intl, date, this.state.now, year);
const date = new Date(timestamp);
const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now) : timeAgoString(intl, date, this.state.now, year!);
return (
<Text {...textProps} theme={theme} tag='time' title={intl.formatDate(date, dateFormatOptions)}>
@ -188,3 +196,5 @@ class RelativeTimestamp extends React.Component {
}
}
export default injectIntl(RelativeTimestamp);

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import throttle from 'lodash/throttle';
import React, { useState, useEffect, useCallback } from 'react';
import { useIntl, MessageDescriptor } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { NavLink } from 'react-router-dom';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { useDispatch } from 'react-redux';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { useSoapboxConfig, useSettings, useTheme } from 'soapbox/hooks';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import { List as ImmutableList } from 'immutable';
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { Text, Icon, Emoji } from 'soapbox/components/ui';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useEffect, useState, useCallback } from 'react';
import { usePopper } from 'react-popper';
import { useHistory } from 'react-router-dom';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useEffect, useRef, useState } from 'react';
import { HotKeys } from 'react-hotkeys';
import { useIntl, FormattedMessage, defineMessages } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState, useRef, useEffect, useMemo } from 'react';
import { FormattedMessage } from 'react-intl';
import { useHistory } from 'react-router-dom';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import debounce from 'lodash/debounce';
import React, { useRef, useCallback } from 'react';
import { FormattedMessage } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useRef } from 'react';
import { useSettings } from 'soapbox/hooks';

@ -4,7 +4,7 @@
* @see soapbox/components/icon
*/
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import InlineSVG from 'react-inlinesvg'; // eslint-disable-line no-restricted-imports

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { NavLink, useLocation } from 'react-router-dom';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import * as React from 'react';
import StillImage from 'soapbox/components/still_image';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
interface IBanner {

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import * as React from 'react';
import { Link } from 'react-router-dom';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
type ButtonThemes = 'primary' | 'secondary' | 'tertiary' | 'accent' | 'danger' | 'transparent' | 'outline'
type ButtonSizes = 'sm' | 'md' | 'lg'

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { Link } from 'react-router-dom';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { Emoji, HStack } from 'soapbox/components/ui';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { forwardRef } from 'react';
const justifyContentOptions = {

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import SvgIcon from '../icon/svg-icon';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import StickyBox from 'react-sticky-box';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import * as React from 'react';
import { defineMessages, useIntl } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
type SIZES = 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 10

@ -5,7 +5,7 @@ import {
Tab as ReachTab,
useTabsContext,
} from '@reach/tabs';
import classNames from 'classnames';
import classNames from 'clsx';
import * as React from 'react';
import { useHistory } from 'react-router-dom';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
type Themes = 'default' | 'danger' | 'primary' | 'muted' | 'subtle' | 'success' | 'inherit' | 'white'
@ -84,7 +84,9 @@ interface IText extends Pick<React.HTMLAttributes<HTMLParagraphElement>, 'danger
/** Whether to truncate the text if its container is too small. */
truncate?: boolean,
/** Font weight of the text. */
weight?: Weights
weight?: Weights,
/** Tooltip title. */
title?: string,
}
/** UI-friendly text container with dark mode support. */
@ -133,4 +135,7 @@ const Text: React.FC<IText> = React.forwardRef(
},
);
export default Text;
export {
Text as default,
IText,
};

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
interface ITextarea extends Pick<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'maxLength' | 'onChange' | 'required' | 'disabled' | 'rows' | 'readOnly'> {

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { HStack, Icon, Text } from 'soapbox/components/ui';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { useIntl, defineMessages } from 'react-intl';

@ -1,7 +1,7 @@
'use strict';
import { QueryClientProvider } from '@tanstack/react-query';
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState, useEffect } from 'react';
import { IntlProvider } from 'react-intl';
import { Provider } from 'react-redux';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState } from 'react';
import Blurhash from 'soapbox/components/blurhash';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useDispatch } from 'react-redux';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import debounce from 'lodash/debounce';
import throttle from 'lodash/throttle';
import PropTypes from 'prop-types';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import {
Map as ImmutableMap,
List as ImmutableList,

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import get from 'lodash/get';
import PropTypes from 'prop-types';
import React from 'react';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { IconButton } from 'soapbox/components/ui';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import { supportsPassiveEvents } from 'detect-passive-events';
import PropTypes from 'prop-types';
import React from 'react';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import { supportsPassiveEvents } from 'detect-passive-events';
import React, { useState, useRef, useEffect } from 'react';
import { useIntl, defineMessages } from 'react-intl';

@ -1,6 +1,6 @@
'use strict';
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import { Map as ImmutableMap } from 'immutable';
import debounce from 'lodash/debounce';
import React, { useCallback } from 'react';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useEffect, useRef } from 'react';
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { length } from 'stringz';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState } from 'react';
import { defineMessages, useIntl, FormattedMessage } from 'react-intl';
import { spring } from 'react-motion';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { useAppSelector } from 'soapbox/hooks';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { FormattedMessage } from 'react-intl';
@ -6,7 +6,7 @@ import { getSettings } from 'soapbox/actions/settings';
import Avatar from 'soapbox/components/avatar';
import DisplayName from 'soapbox/components/display-name';
import Permalink from 'soapbox/components/permalink';
import RelativeTimestamp from 'soapbox/components/relative_timestamp';
import RelativeTimestamp from 'soapbox/components/relative-timestamp';
import { Text } from 'soapbox/components/ui';
import ActionButton from 'soapbox/features/ui/components/action-button';
import { useAppSelector } from 'soapbox/hooks';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { useDispatch } from 'react-redux';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState } from 'react';
import Icon from 'soapbox/components/icon';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useEffect, useState } from 'react';
import { FormattedMessage } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React, { useState, useRef } from 'react';
import { v4 as uuidv4 } from 'uuid';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import PropTypes from 'prop-types';
import React from 'react';
import { defineMessages, injectIntl } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import PropTypes from 'prop-types';
import React from 'react';
import ImmutablePropTypes from 'react-immutable-proptypes';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import PropTypes from 'prop-types';
import React from 'react';
import { FormattedMessage } from 'react-intl';

@ -1,4 +1,4 @@
import classNames from 'classnames';
import classNames from 'clsx';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save