Merge branch 'long-name-fixes' into 'develop'
Fix overflow problems in various places See merge request soapbox-pub/soapbox!2487
This commit is contained in:
commit
c0c0dc1cc2
14 changed files with 33 additions and 23 deletions
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Posts: Support posts filtering on recent Mastodon versions
|
- Posts: Support posts filtering on recent Mastodon versions
|
||||||
- Reactions: Support custom emoji reactions
|
- Reactions: Support custom emoji reactions
|
||||||
- Compatbility: Support Mastodon v2 timeline filters.
|
- Compatbility: Support Mastodon v2 timeline filters.
|
||||||
|
- Compatbility: Preliminary support for Ditto backend.
|
||||||
- Posts: Support dislikes on Friendica.
|
- Posts: Support dislikes on Friendica.
|
||||||
- UI: added a character counter to some textareas.
|
- UI: added a character counter to some textareas.
|
||||||
|
|
||||||
|
@ -30,6 +31,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- 18n: fixed Chinese language being detected from the browser.
|
- 18n: fixed Chinese language being detected from the browser.
|
||||||
- Conversations: fixed pagination (Mastodon).
|
- Conversations: fixed pagination (Mastodon).
|
||||||
- Compatibility: fix version parsing for Friendica.
|
- Compatibility: fix version parsing for Friendica.
|
||||||
|
- UI: fixed various overflow issues related to long usernames.
|
||||||
|
- UI: fixed display of Markdown code blocks in the reply indicator.
|
||||||
|
|
||||||
## [3.2.0] - 2023-02-15
|
## [3.2.0] - 2023-02-15
|
||||||
|
|
||||||
|
|
|
@ -142,7 +142,7 @@ const deleteStatusModal = (intl: IntlShape, statusId: string, afterConfirm = ()
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
icon: require('@tabler/icons/trash.svg'),
|
icon: require('@tabler/icons/trash.svg'),
|
||||||
heading: intl.formatMessage(messages.deleteStatusHeading),
|
heading: intl.formatMessage(messages.deleteStatusHeading),
|
||||||
message: intl.formatMessage(messages.deleteStatusPrompt, { acct }),
|
message: intl.formatMessage(messages.deleteStatusPrompt, { acct: <strong className='break-words'>{acct}</strong> }),
|
||||||
confirm: intl.formatMessage(messages.deleteStatusConfirm),
|
confirm: intl.formatMessage(messages.deleteStatusConfirm),
|
||||||
onConfirm: () => {
|
onConfirm: () => {
|
||||||
dispatch(deleteStatus(statusId)).then(() => {
|
dispatch(deleteStatus(statusId)).then(() => {
|
||||||
|
|
|
@ -56,8 +56,7 @@ const ListItem: React.FC<IListItem> = ({ label, hint, children, onClick, onSelec
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Comp
|
<Comp
|
||||||
className={clsx({
|
className={clsx('flex items-center justify-between overflow-hidden bg-gradient-to-r from-gradient-start/20 to-gradient-end/20 px-4 py-2 first:rounded-t-lg last:rounded-b-lg dark:from-gradient-start/10 dark:to-gradient-end/10', {
|
||||||
'flex items-center justify-between px-4 py-2 first:rounded-t-lg last:rounded-b-lg bg-gradient-to-r from-gradient-start/20 to-gradient-end/20 dark:from-gradient-start/10 dark:to-gradient-end/10': true,
|
|
||||||
'cursor-pointer hover:from-gradient-start/30 hover:to-gradient-end/30 dark:hover:from-gradient-start/5 dark:hover:to-gradient-end/5': typeof onClick !== 'undefined' || typeof onSelect !== 'undefined',
|
'cursor-pointer hover:from-gradient-start/30 hover:to-gradient-end/30 dark:hover:from-gradient-start/5 dark:hover:to-gradient-end/5': typeof onClick !== 'undefined' || typeof onSelect !== 'undefined',
|
||||||
})}
|
})}
|
||||||
{...linkProps}
|
{...linkProps}
|
||||||
|
@ -71,7 +70,7 @@ const ListItem: React.FC<IListItem> = ({ label, hint, children, onClick, onSelec
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{onClick ? (
|
{onClick ? (
|
||||||
<HStack space={1} alignItems='center' className='text-gray-700 dark:text-gray-600'>
|
<HStack space={1} alignItems='center' className='overflow-hidden text-gray-700 dark:text-gray-600'>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
<Icon src={require('@tabler/icons/chevron-right.svg')} className='ml-1 rtl:rotate-180' />
|
<Icon src={require('@tabler/icons/chevron-right.svg')} className='ml-1 rtl:rotate-180' />
|
||||||
|
|
|
@ -258,8 +258,8 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
|
||||||
|
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
icon: require('@tabler/icons/ban.svg'),
|
icon: require('@tabler/icons/ban.svg'),
|
||||||
heading: <FormattedMessage id='confirmations.block.heading' defaultMessage='Block @{name}' values={{ name: account.get('acct') }} />,
|
heading: <FormattedMessage id='confirmations.block.heading' defaultMessage='Block @{name}' values={{ name: account.acct }} />,
|
||||||
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
|
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong className='break-words'>@{account.acct}</strong> }} />,
|
||||||
confirm: intl.formatMessage(messages.blockConfirm),
|
confirm: intl.formatMessage(messages.blockConfirm),
|
||||||
onConfirm: () => dispatch(blockAccount(account.id)),
|
onConfirm: () => dispatch(blockAccount(account.id)),
|
||||||
secondary: intl.formatMessage(messages.blockAndReport),
|
secondary: intl.formatMessage(messages.blockAndReport),
|
||||||
|
@ -313,7 +313,7 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
|
||||||
|
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
heading: intl.formatMessage(messages.deleteHeading),
|
heading: intl.formatMessage(messages.deleteHeading),
|
||||||
message: intl.formatMessage(messages.deleteFromGroupMessage, { name: account.username }),
|
message: intl.formatMessage(messages.deleteFromGroupMessage, { name: <strong className='break-words'>{account.username}</strong> }),
|
||||||
confirm: intl.formatMessage(messages.deleteConfirm),
|
confirm: intl.formatMessage(messages.deleteConfirm),
|
||||||
onConfirm: () => dispatch(groupDeleteStatus((status.group as Group).id, status.id)),
|
onConfirm: () => dispatch(groupDeleteStatus((status.group as Group).id, status.id)),
|
||||||
}));
|
}));
|
||||||
|
@ -324,7 +324,7 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
|
||||||
|
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
heading: intl.formatMessage(messages.kickFromGroupHeading),
|
heading: intl.formatMessage(messages.kickFromGroupHeading),
|
||||||
message: intl.formatMessage(messages.kickFromGroupMessage, { name: account.username }),
|
message: intl.formatMessage(messages.kickFromGroupMessage, { name: <strong className='break-words'>{account.username}</strong> }),
|
||||||
confirm: intl.formatMessage(messages.kickFromGroupConfirm),
|
confirm: intl.formatMessage(messages.kickFromGroupConfirm),
|
||||||
onConfirm: () => dispatch(groupKick((status.group as Group).id, account.id)),
|
onConfirm: () => dispatch(groupKick((status.group as Group).id, account.id)),
|
||||||
}));
|
}));
|
||||||
|
@ -335,7 +335,7 @@ const StatusActionBar: React.FC<IStatusActionBar> = ({
|
||||||
|
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
heading: intl.formatMessage(messages.blockFromGroupHeading),
|
heading: intl.formatMessage(messages.blockFromGroupHeading),
|
||||||
message: intl.formatMessage(messages.blockFromGroupMessage, { name: account.username }),
|
message: intl.formatMessage(messages.blockFromGroupMessage, { name: <strong className='break-words'>{account.username}</strong> }),
|
||||||
confirm: intl.formatMessage(messages.blockFromGroupConfirm),
|
confirm: intl.formatMessage(messages.blockFromGroupConfirm),
|
||||||
onConfirm: () => dispatch(groupBlock((status.group as Group).id, account.id)),
|
onConfirm: () => dispatch(groupBlock((status.group as Group).id, account.id)),
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -102,7 +102,7 @@ const Modal = React.forwardRef<HTMLDivElement, IModal>(({
|
||||||
'flex-row-reverse': closePosition === 'left',
|
'flex-row-reverse': closePosition === 'left',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<h3 className='grow text-lg font-bold leading-6 text-gray-900 dark:text-white'>
|
<h3 className='grow truncate text-lg font-bold leading-6 text-gray-900 dark:text-white'>
|
||||||
{title}
|
{title}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
|
|
|
@ -130,7 +130,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
icon: require('@tabler/icons/ban.svg'),
|
icon: require('@tabler/icons/ban.svg'),
|
||||||
heading: <FormattedMessage id='confirmations.block.heading' defaultMessage='Block @{name}' values={{ name: account.acct }} />,
|
heading: <FormattedMessage id='confirmations.block.heading' defaultMessage='Block @{name}' values={{ name: account.acct }} />,
|
||||||
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.acct}</strong> }} />,
|
message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong className='break-words'>@{account.acct}</strong> }} />,
|
||||||
confirm: intl.formatMessage(messages.blockConfirm),
|
confirm: intl.formatMessage(messages.blockConfirm),
|
||||||
onConfirm: () => dispatch(blockAccount(account.id)),
|
onConfirm: () => dispatch(blockAccount(account.id)),
|
||||||
secondary: intl.formatMessage(messages.blockAndReport),
|
secondary: intl.formatMessage(messages.blockAndReport),
|
||||||
|
@ -215,7 +215,7 @@ const Header: React.FC<IHeader> = ({ account }) => {
|
||||||
const unfollowModal = getSettings(getState()).get('unfollowModal');
|
const unfollowModal = getSettings(getState()).get('unfollowModal');
|
||||||
if (unfollowModal) {
|
if (unfollowModal) {
|
||||||
dispatch(openModal('CONFIRM', {
|
dispatch(openModal('CONFIRM', {
|
||||||
message: <FormattedMessage id='confirmations.remove_from_followers.message' defaultMessage='Are you sure you want to remove {name} from your followers?' values={{ name: <strong>@{account.acct}</strong> }} />,
|
message: <FormattedMessage id='confirmations.remove_from_followers.message' defaultMessage='Are you sure you want to remove {name} from your followers?' values={{ name: <strong className='break-words'>@{account.acct}</strong> }} />,
|
||||||
confirm: intl.formatMessage(messages.removeFromFollowersConfirm),
|
confirm: intl.formatMessage(messages.removeFromFollowersConfirm),
|
||||||
onConfirm: () => dispatch(removeFromFollowers(account.id)),
|
onConfirm: () => dispatch(removeFromFollowers(account.id)),
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -2,7 +2,8 @@ import clsx from 'clsx';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import AttachmentThumbs from 'soapbox/components/attachment-thumbs';
|
import AttachmentThumbs from 'soapbox/components/attachment-thumbs';
|
||||||
import { Stack, Text } from 'soapbox/components/ui';
|
import Markup from 'soapbox/components/markup';
|
||||||
|
import { Stack } from 'soapbox/components/ui';
|
||||||
import AccountContainer from 'soapbox/containers/account-container';
|
import AccountContainer from 'soapbox/containers/account-container';
|
||||||
import { isRtl } from 'soapbox/rtl';
|
import { isRtl } from 'soapbox/rtl';
|
||||||
|
|
||||||
|
@ -45,8 +46,8 @@ const ReplyIndicator: React.FC<IReplyIndicator> = ({ className, status, hideActi
|
||||||
hideActions={hideActions}
|
hideActions={hideActions}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Text
|
<Markup
|
||||||
className='status__content break-words'
|
className='break-words'
|
||||||
size='sm'
|
size='sm'
|
||||||
dangerouslySetInnerHTML={{ __html: status.contentHtml }}
|
dangerouslySetInnerHTML={{ __html: status.contentHtml }}
|
||||||
direction={isRtl(status.search_index) ? 'rtl' : 'ltr'}
|
direction={isRtl(status.search_index) ? 'rtl' : 'ltr'}
|
||||||
|
|
|
@ -238,11 +238,11 @@ const SearchResults = () => {
|
||||||
{filterByAccount ? (
|
{filterByAccount ? (
|
||||||
<HStack className='mb-4 border-b border-solid border-gray-200 px-2 pb-4 dark:border-gray-800' space={2}>
|
<HStack className='mb-4 border-b border-solid border-gray-200 px-2 pb-4 dark:border-gray-800' space={2}>
|
||||||
<IconButton iconClassName='h-5 w-5' src={require('@tabler/icons/x.svg')} onClick={handleUnsetAccount} />
|
<IconButton iconClassName='h-5 w-5' src={require('@tabler/icons/x.svg')} onClick={handleUnsetAccount} />
|
||||||
<Text>
|
<Text truncate>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='search_results.filter_message'
|
id='search_results.filter_message'
|
||||||
defaultMessage='You are searching for posts from @{acct}.'
|
defaultMessage='You are searching for posts from @{acct}.'
|
||||||
values={{ acct: account }}
|
values={{ acct: <strong className='break-words'>{account}</strong> }}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
|
@ -124,7 +124,7 @@ const accountToCredentials = (account: Account): AccountCredentials => {
|
||||||
discoverable: account.discoverable,
|
discoverable: account.discoverable,
|
||||||
bot: account.bot,
|
bot: account.bot,
|
||||||
display_name: account.display_name,
|
display_name: account.display_name,
|
||||||
note: account.source.get('note'),
|
note: account.source.get('note', ''),
|
||||||
locked: account.locked,
|
locked: account.locked,
|
||||||
fields_attributes: [...account.source.get<Iterable<AccountCredentialsField>>('fields', ImmutableList()).toJS()],
|
fields_attributes: [...account.source.get<Iterable<AccountCredentialsField>>('fields', ImmutableList()).toJS()],
|
||||||
stranger_notifications: account.getIn(['pleroma', 'notification_settings', 'block_from_strangers']) === true,
|
stranger_notifications: account.getIn(['pleroma', 'notification_settings', 'block_from_strangers']) === true,
|
||||||
|
|
|
@ -74,7 +74,7 @@ const Settings = () => {
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<List>
|
<List>
|
||||||
<ListItem label={intl.formatMessage(messages.editProfile)} onClick={navigateToEditProfile}>
|
<ListItem label={intl.formatMessage(messages.editProfile)} onClick={navigateToEditProfile}>
|
||||||
<span>{displayName}</span>
|
<span className='max-w-full truncate'>{displayName}</span>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</List>
|
</List>
|
||||||
</CardBody>
|
</CardBody>
|
||||||
|
|
|
@ -60,7 +60,7 @@ const MuteModal = () => {
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='confirmations.mute.message'
|
id='confirmations.mute.message'
|
||||||
defaultMessage='Are you sure you want to mute {name}?'
|
defaultMessage='Are you sure you want to mute {name}?'
|
||||||
values={{ name: <strong>@{account.acct}</strong> }}
|
values={{ name: <strong className='break-words'>@{account.acct}</strong> }}
|
||||||
/>
|
/>
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
|
|
|
@ -120,7 +120,7 @@ const ProfileInfoPanel: React.FC<IProfileInfoPanel> = ({ account, username }) =>
|
||||||
<Stack space={2}>
|
<Stack space={2}>
|
||||||
<Stack>
|
<Stack>
|
||||||
<HStack space={1} alignItems='center'>
|
<HStack space={1} alignItems='center'>
|
||||||
<Text size='sm' theme='muted' direction='ltr'>
|
<Text size='sm' theme='muted' direction='ltr' truncate>
|
||||||
@{username}
|
@{username}
|
||||||
</Text>
|
</Text>
|
||||||
</HStack>
|
</HStack>
|
||||||
|
|
|
@ -59,7 +59,7 @@ const UserPanel: React.FC<IUserPanel> = ({ accountId, action, badges, domain })
|
||||||
<Stack>
|
<Stack>
|
||||||
<Link to={`/@${account.acct}`}>
|
<Link to={`/@${account.acct}`}>
|
||||||
<HStack space={1} alignItems='center'>
|
<HStack space={1} alignItems='center'>
|
||||||
<Text size='lg' weight='bold' dangerouslySetInnerHTML={displayNameHtml} />
|
<Text size='lg' weight='bold' dangerouslySetInnerHTML={displayNameHtml} truncate />
|
||||||
|
|
||||||
{verified && <VerificationBadge />}
|
{verified && <VerificationBadge />}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ const UserPanel: React.FC<IUserPanel> = ({ accountId, action, badges, domain })
|
||||||
</HStack>
|
</HStack>
|
||||||
</Link>
|
</Link>
|
||||||
|
|
||||||
<Text size='sm' theme='muted'>
|
<Text size='sm' theme='muted' truncate>
|
||||||
@{getAcct(account, fqn)}
|
@{getAcct(account, fqn)}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
|
@ -16,6 +16,12 @@ const overrides = custom('features');
|
||||||
/** Truthy array convenience function */
|
/** Truthy array convenience function */
|
||||||
const any = (arr: Array<any>): boolean => arr.some(Boolean);
|
const any = (arr: Array<any>): boolean => arr.some(Boolean);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ditto, a Nostr server with Mastodon API.
|
||||||
|
* @see {@link https://gitlab.com/soapbox-pub/ditto}
|
||||||
|
*/
|
||||||
|
export const DITTO = 'Ditto';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Friendica, decentralized social platform implementing multiple federation protocols.
|
* Friendica, decentralized social platform implementing multiple federation protocols.
|
||||||
* @see {@link https://friendi.ca/}
|
* @see {@link https://friendi.ca/}
|
||||||
|
@ -137,6 +143,7 @@ const getInstanceFeatures = (instance: Instance) => {
|
||||||
v.software === PLEROMA && gte(v.version, '2.4.50'),
|
v.software === PLEROMA && gte(v.version, '2.4.50'),
|
||||||
v.software === TAKAHE && gte(v.version, '0.6.1'),
|
v.software === TAKAHE && gte(v.version, '0.6.1'),
|
||||||
v.software === TRUTHSOCIAL,
|
v.software === TRUTHSOCIAL,
|
||||||
|
v.software === DITTO,
|
||||||
]),
|
]),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue