diff --git a/package.json b/package.json index 2ffe7dfce..ebbeaa9b9 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "@soapbox.pub/wasmboy": "^0.8.0", "@soapbox/nspec": "npm:@jsr/soapbox__nspec", "@soapbox/weblock": "npm:@jsr/soapbox__weblock", - "@tabler/icons": "^2.0.0", + "@tabler/icons": "^3.1.0", "@tailwindcss/aspect-ratio": "^0.4.2", "@tailwindcss/forms": "^0.5.7", "@tailwindcss/typography": "^0.5.10", diff --git a/src/actions/compose.ts b/src/actions/compose.ts index ed51f2a0c..99f84298e 100644 --- a/src/actions/compose.ts +++ b/src/actions/compose.ts @@ -89,6 +89,8 @@ const COMPOSE_SET_STATUS = 'COMPOSE_SET_STATUS' as const; const COMPOSE_EDITOR_STATE_SET = 'COMPOSE_EDITOR_STATE_SET' as const; +const COMPOSE_CHANGE_MEDIA_ORDER = 'COMPOSE_CHANGE_MEDIA_ORDER' as const; + const messages = defineMessages({ scheduleError: { id: 'compose.invalid_schedule', defaultMessage: 'You must schedule a post at least 5 minutes out.' }, success: { id: 'compose.submit_success', defaultMessage: 'Your post was sent!' }, @@ -851,6 +853,13 @@ const setEditorState = (composeId: string, editorState: EditorState | string | n editorState: editorState, }); +const changeMediaOrder = (composeId: string, a: string, b: string) => ({ + type: COMPOSE_CHANGE_MEDIA_ORDER, + id: composeId, + a, + b, +}); + type ComposeAction = ComposeSetStatusAction | ReturnType @@ -897,6 +906,7 @@ type ComposeAction = | ComposeRemoveFromMentionsAction | ComposeEventReplyAction | ReturnType + | ReturnType export { COMPOSE_CHANGE, @@ -945,6 +955,7 @@ export { COMPOSE_SET_STATUS, COMPOSE_EDITOR_STATE_SET, COMPOSE_SET_GROUP_TIMELINE_VISIBLE, + COMPOSE_CHANGE_MEDIA_ORDER, setComposeToStatus, changeCompose, replyCompose, @@ -1000,5 +1011,6 @@ export { removeFromMentions, eventDiscussionCompose, setEditorState, + changeMediaOrder, type ComposeAction, }; diff --git a/src/actions/moderation.tsx b/src/actions/moderation.tsx index 52b418b11..35ad6a4d7 100644 --- a/src/actions/moderation.tsx +++ b/src/actions/moderation.tsx @@ -58,7 +58,7 @@ const deactivateUserModal = (intl: IntlShape, accountId: string, afterConfirm = ); dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/user-off.svg'), + icon: require('@tabler/icons/outline/user-off.svg'), heading: intl.formatMessage(messages.deactivateUserHeading, { acct }), message, confirm: intl.formatMessage(messages.deactivateUserConfirm, { name }), @@ -96,7 +96,7 @@ const deleteUserModal = (intl: IntlShape, accountId: string, afterConfirm = () = const checkbox = local ? intl.formatMessage(messages.deleteLocalUserCheckbox) : false; dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/user-minus.svg'), + icon: require('@tabler/icons/outline/user-minus.svg'), heading: intl.formatMessage(messages.deleteUserHeading, { acct }), message, confirm, @@ -118,7 +118,7 @@ const toggleStatusSensitivityModal = (intl: IntlShape, statusId: string, sensiti const acct = state.statuses.get(statusId)!.account.acct; dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/alert-triangle.svg'), + icon: require('@tabler/icons/outline/alert-triangle.svg'), heading: intl.formatMessage(sensitive === false ? messages.markStatusSensitiveHeading : messages.markStatusNotSensitiveHeading), message: intl.formatMessage(sensitive === false ? messages.markStatusSensitivePrompt : messages.markStatusNotSensitivePrompt, { acct }), confirm: intl.formatMessage(sensitive === false ? messages.markStatusSensitiveConfirm : messages.markStatusNotSensitiveConfirm), @@ -138,7 +138,7 @@ const deleteStatusModal = (intl: IntlShape, statusId: string, afterConfirm = () const acct = state.statuses.get(statusId)!.account.acct; dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), heading: intl.formatMessage(messages.deleteStatusHeading), message: intl.formatMessage(messages.deleteStatusPrompt, { acct: {acct} }), confirm: intl.formatMessage(messages.deleteStatusConfirm), diff --git a/src/actions/remote-timeline.ts b/src/actions/remote-timeline.ts index cb21126b9..ac1277aec 100644 --- a/src/actions/remote-timeline.ts +++ b/src/actions/remote-timeline.ts @@ -1,11 +1,11 @@ import { getSettings, changeSetting } from 'soapbox/actions/settings'; -import type { OrderedSet as ImmutableOrderedSet } from 'immutable'; +import type { List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable'; import type { AppDispatch, RootState } from 'soapbox/store'; const getPinnedHosts = (state: RootState) => { const settings = getSettings(state); - return settings.getIn(['remote_timeline', 'pinnedHosts']) as ImmutableOrderedSet; + return settings.getIn(['remote_timeline', 'pinnedHosts']) as ImmutableList | ImmutableOrderedSet; }; const pinHost = (host: string) => @@ -13,7 +13,7 @@ const pinHost = (host: string) => const state = getState(); const pinnedHosts = getPinnedHosts(state); - return dispatch(changeSetting(['remote_timeline', 'pinnedHosts'], pinnedHosts.add(host))); + return dispatch(changeSetting(['remote_timeline', 'pinnedHosts'], pinnedHosts.toOrderedSet().add(host))); }; const unpinHost = (host: string) => @@ -21,7 +21,7 @@ const unpinHost = (host: string) => const state = getState(); const pinnedHosts = getPinnedHosts(state); - return dispatch(changeSetting(['remote_timeline', 'pinnedHosts'], pinnedHosts.remove(host))); + return dispatch(changeSetting(['remote_timeline', 'pinnedHosts'], pinnedHosts.toOrderedSet().remove(host))); }; export { diff --git a/src/actions/settings.ts b/src/actions/settings.ts index ae6a3ec35..ae26af50a 100644 --- a/src/actions/settings.ts +++ b/src/actions/settings.ts @@ -1,4 +1,4 @@ -import { Map as ImmutableMap, List as ImmutableList, OrderedSet as ImmutableOrderedSet } from 'immutable'; +import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { defineMessage } from 'react-intl'; import { createSelector } from 'reselect'; import { v4 as uuid } from 'uuid'; @@ -169,7 +169,7 @@ const defaultSettings = ImmutableMap({ ]), remote_timeline: ImmutableMap({ - pinnedHosts: ImmutableOrderedSet(), + pinnedHosts: ImmutableList(), }), }); diff --git a/src/api/hooks/nostr/useSignerStream.ts b/src/api/hooks/nostr/useSignerStream.ts index 460cfd9d6..b163469e3 100644 --- a/src/api/hooks/nostr/useSignerStream.ts +++ b/src/api/hooks/nostr/useSignerStream.ts @@ -64,13 +64,20 @@ function useSignerStream() { useEffect(() => { if (!relay || !pubkey) return; + const controller = new AbortController(); + const signal = controller.signal; + (async() => { - for await (const msg of relay.req([{ kinds: [24133, 23194], authors: [pubkey], limit: 0 }])) { + for await (const msg of relay.req([{ kinds: [24133, 23194], authors: [pubkey], limit: 0 }], { signal })) { if (msg[0] === 'EVENT') handleEvent(msg[2]); } })(); - }, [relay, pubkey]); + return () => { + controller.abort(); + }; + + }, [relay, pubkey, signer]); } export { useSignerStream }; diff --git a/src/components/account-search.tsx b/src/components/account-search.tsx index 50e6e8ee7..dec244674 100644 --- a/src/components/account-search.tsx +++ b/src/components/account-search.tsx @@ -76,12 +76,12 @@ const AccountSearch: React.FC = ({ onSelected, ...rest }) => { onClick={handleClear} > diff --git a/src/components/account.tsx b/src/components/account.tsx index d4c252654..5751b2c3a 100644 --- a/src/components/account.tsx +++ b/src/components/account.tsx @@ -264,7 +264,7 @@ const Account = ({ <> · - + ) : null} diff --git a/src/components/authorize-reject-buttons.tsx b/src/components/authorize-reject-buttons.tsx index aa6a39ab7..aa1bd9d74 100644 --- a/src/components/authorize-reject-buttons.tsx +++ b/src/components/authorize-reject-buttons.tsx @@ -106,7 +106,7 @@ const AuthorizeRejectButtons: React.FC = ({ onAuthorize = ({ onAuthorize /> = ({ theme, icon, } > = { house: homeIcon, diff --git a/src/components/birthday-input.tsx b/src/components/birthday-input.tsx index 62043bd51..53fbed409 100644 --- a/src/components/birthday-input.tsx +++ b/src/components/birthday-input.tsx @@ -70,7 +70,7 @@ const BirthdayInput: React.FC = ({ value, onChange, required })
= ({ value, onChange, required }) {intl.formatDate(date, { month: 'long' })} = ({ value, onChange, required })
= ({ value, onChange, required }) {intl.formatDate(date, { year: 'numeric' })} = ({ domain }) => { // const onBlockDomain = () => { // dispatch(openModal('CONFIRM', { - // icon: require('@tabler/icons/ban.svg'), + // icon: require('@tabler/icons/outline/ban.svg'), // heading: , // message: {domain} }} />, // confirm: intl.formatMessage(messages.blockDomainConfirm), @@ -38,7 +38,7 @@ const Domain: React.FC = ({ domain }) => { {domain} - + ); }; diff --git a/src/components/dropdown-menu/dropdown-menu.tsx b/src/components/dropdown-menu/dropdown-menu.tsx index 2c94f9be0..7bdaff994 100644 --- a/src/components/dropdown-menu/dropdown-menu.tsx +++ b/src/components/dropdown-menu/dropdown-menu.tsx @@ -41,7 +41,7 @@ const DropdownMenu = (props: IDropdownMenu) => { onOpen, onShiftClick, placement: initialPlacement = 'top', - src = require('@tabler/icons/dots.svg'), + src = require('@tabler/icons/outline/dots.svg'), title = 'Menu', ...filteredProps } = props; diff --git a/src/components/event-preview.tsx b/src/components/event-preview.tsx index 710075764..5ef36a4d5 100644 --- a/src/components/event-preview.tsx +++ b/src/components/event-preview.tsx @@ -67,7 +67,7 @@ const EventPreview: React.FC = ({ status, className, hideAction,
- + {account.verified && } @@ -78,7 +78,7 @@ const EventPreview: React.FC = ({ status, className, hideAction, {event.location && ( - + {event.location.get('name')} diff --git a/src/components/gameboy.tsx b/src/components/gameboy.tsx index 234b62097..fca9ab16b 100644 --- a/src/components/gameboy.tsx +++ b/src/components/gameboy.tsx @@ -138,13 +138,13 @@ const Gameboy: React.FC = ({ className, src, aspect = 'normal', onFocu theme='transparent' className='text-white' onClick={togglePaused} - src={paused ? require('@tabler/icons/player-play.svg') : require('@tabler/icons/player-pause.svg')} + src={paused ? require('@tabler/icons/outline/player-play.svg') : require('@tabler/icons/outline/player-pause.svg')} /> @@ -152,14 +152,14 @@ const Gameboy: React.FC = ({ className, src, aspect = 'normal', onFocu diff --git a/src/components/list.tsx b/src/components/list.tsx index 303690593..b26eea116 100644 --- a/src/components/list.tsx +++ b/src/components/list.tsx @@ -73,7 +73,7 @@ const ListItem: React.FC = ({ label, hint, children, to, onClick, onS {children} - + ) : null} @@ -91,7 +91,7 @@ const ListItem: React.FC = ({ label, hint, children, to, onClick, onS } > = ({ disabled, maxId, onClick }) => { return ( ); }; diff --git a/src/components/location-search.tsx b/src/components/location-search.tsx index d2d8d4f29..b3c9430b6 100644 --- a/src/components/location-search.tsx +++ b/src/components/location-search.tsx @@ -100,8 +100,8 @@ const LocationSearch: React.FC = ({ onSelected }) => { renderSuggestion={AutosuggestLocation} />
- - + +
); diff --git a/src/components/media-gallery.tsx b/src/components/media-gallery.tsx index eb4f1988a..5eef12bcc 100644 --- a/src/components/media-gallery.tsx +++ b/src/components/media-gallery.tsx @@ -164,7 +164,7 @@ const Item: React.FC = ({ const attachmentIcon = ( ); @@ -240,7 +240,7 @@ const Item: React.FC = ({ target='_blank' title={attachment.description} > - + {ext} ); diff --git a/src/components/modal-root.tsx b/src/components/modal-root.tsx index 1c755b995..4216431b8 100644 --- a/src/components/modal-root.tsx +++ b/src/components/modal-root.tsx @@ -75,7 +75,7 @@ const ModalRoot: React.FC = ({ children, onCancel, onClose, type }) if (hasComposeContent && type === 'COMPOSE') { const isEditing = compose!.id !== null; dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), heading: isEditing ? : , @@ -94,7 +94,7 @@ const ModalRoot: React.FC = ({ children, onCancel, onClose, type }) } else if (hasEventComposeContent && type === 'COMPOSE_EVENT') { const isEditing = getState().compose_event.id !== null; dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), heading: isEditing ? : , diff --git a/src/components/pending-items-row.tsx b/src/components/pending-items-row.tsx index f86be15d3..e37714b76 100644 --- a/src/components/pending-items-row.tsx +++ b/src/components/pending-items-row.tsx @@ -25,7 +25,7 @@ const PendingItemsRow: React.FC = ({ to, count, size = 'md' }) })} > = ({ to, count, size = 'md' }) diff --git a/src/components/polls/poll-option.tsx b/src/components/polls/poll-option.tsx index 7fb7a64d8..83b12a1e3 100644 --- a/src/components/polls/poll-option.tsx +++ b/src/components/polls/poll-option.tsx @@ -86,7 +86,7 @@ const PollOptionText: React.FC = ({ poll, option, index, active aria-label={option.title} > {active && ( - + )}
@@ -143,7 +143,7 @@ const PollOption: React.FC = (props): JSX.Element | null => { {voted ? ( diff --git a/src/components/preview-card.tsx b/src/components/preview-card.tsx index 16a1a467c..9fbbb70b8 100644 --- a/src/components/preview-card.tsx +++ b/src/components/preview-card.tsx @@ -135,7 +135,7 @@ const PreviewCard: React.FC = ({ )} - + {card.provider_name} @@ -168,10 +168,10 @@ const PreviewCard: React.FC = ({ if (embedded) { embed = renderVideo(); } else { - let iconVariant = require('@tabler/icons/player-play.svg'); + let iconVariant = require('@tabler/icons/outline/player-play.svg'); if (card.type === 'photo') { - iconVariant = require('@tabler/icons/zoom-in.svg'); + iconVariant = require('@tabler/icons/outline/zoom-in.svg'); } embed = ( @@ -198,7 +198,7 @@ const PreviewCard: React.FC = ({ className='text-gray-700 hover:text-gray-900 dark:text-gray-500 dark:hover:text-gray-100' > diff --git a/src/components/profile-hover-card.tsx b/src/components/profile-hover-card.tsx index 0def77693..db555e226 100644 --- a/src/components/profile-hover-card.tsx +++ b/src/components/profile-hover-card.tsx @@ -119,7 +119,7 @@ export const ProfileHoverCard: React.FC = ({ visible = true } {account.local ? ( diff --git a/src/components/quoted-status-indicator.tsx b/src/components/quoted-status-indicator.tsx new file mode 100644 index 000000000..493db5f19 --- /dev/null +++ b/src/components/quoted-status-indicator.tsx @@ -0,0 +1,27 @@ +import React, { useCallback } from 'react'; + +import { HStack, Icon, Text } from 'soapbox/components/ui'; +import { useAppSelector } from 'soapbox/hooks'; +import { makeGetStatus } from 'soapbox/selectors'; + +interface IQuotedStatusIndicator { + /** The quoted status id. */ + statusId: string; +} + +const QuotedStatusIndicator: React.FC = ({ statusId }) => { + const getStatus = useCallback(makeGetStatus(), []); + + const status = useAppSelector(state => getStatus(state, { id: statusId })); + + if (!status) return null; + + return ( + + + {status.url} + + ); +}; + +export default QuotedStatusIndicator; diff --git a/src/components/quoted-status.tsx b/src/components/quoted-status.tsx index 4470cd453..b90e753e6 100644 --- a/src/components/quoted-status.tsx +++ b/src/components/quoted-status.tsx @@ -11,6 +11,7 @@ import { defaultMediaVisibility } from 'soapbox/utils/status'; import EventPreview from './event-preview'; import OutlineBox from './outline-box'; +import QuotedStatusIndicator from './quoted-status-indicator'; import StatusContent from './status-content'; import StatusReplyMentions from './status-reply-mentions'; import SensitiveContentOverlay from './statuses/sensitive-content-overlay'; @@ -84,7 +85,7 @@ const QuotedStatus: React.FC = ({ status, onCancel, compose }) => if (onCancel) { actions = { onActionClick: handleClose, - actionIcon: require('@tabler/icons/x.svg'), + actionIcon: require('@tabler/icons/outline/x.svg'), actionAlignment: 'top', actionTitle: intl.formatMessage(messages.cancel), }; @@ -132,6 +133,8 @@ const QuotedStatus: React.FC = ({ status, onCancel, compose }) => collapsable /> + {status.quote && } + {status.media_attachments.size > 0 && ( = ({ > diff --git a/src/components/sidebar-menu.tsx b/src/components/sidebar-menu.tsx index e79853adc..f8d091b20 100644 --- a/src/components/sidebar-menu.tsx +++ b/src/components/sidebar-menu.tsx @@ -161,7 +161,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { { @@ -192,7 +192,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {(account.locked || followRequestsCount > 0) && ( @@ -201,7 +201,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {features.bookmarks && ( @@ -210,7 +210,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {features.groups && ( @@ -219,7 +219,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {features.lists && ( @@ -228,7 +228,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {features.events && ( @@ -237,7 +237,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {settings.get('isDeveloper') && ( @@ -248,7 +248,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { : } onClick={onClose} /> @@ -256,7 +256,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {features.federating && ( } onClick={onClose} /> @@ -267,21 +267,21 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { @@ -289,7 +289,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {features.federating && ( @@ -298,7 +298,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {(features.filters || features.filtersV2) && ( @@ -307,7 +307,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {features.followedHashtagsList && ( @@ -316,7 +316,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { {account.admin && ( @@ -326,7 +326,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { @@ -341,7 +341,7 @@ const SidebarMenu: React.FC = (): JSX.Element | null => { { {otherAccounts.map(account => renderAccount(account))} - + {intl.formatMessage(messages.addAccount)}
diff --git a/src/components/sidebar-navigation-link.tsx b/src/components/sidebar-navigation-link.tsx index 906fabc42..d1b7465bf 100644 --- a/src/components/sidebar-navigation-link.tsx +++ b/src/components/sidebar-navigation-link.tsx @@ -11,6 +11,8 @@ interface ISidebarNavigationLink { countMax?: number; /** URL to an SVG icon. */ icon: string; + /** URL to an SVG icon for active state. */ + activeIcon?: string; /** Link label. */ text: React.ReactNode; /** Route to an internal page. */ @@ -21,7 +23,7 @@ interface ISidebarNavigationLink { /** Desktop sidebar navigation link. */ const SidebarNavigationLink = React.forwardRef((props: ISidebarNavigationLink, ref: React.ForwardedRef): JSX.Element => { - const { icon, text, to = '', count, countMax, onClick } = props; + const { icon, activeIcon, text, to = '', count, countMax, onClick } = props; const isActive = location.pathname === to; const handleClick: React.EventHandler = (e) => { @@ -45,7 +47,7 @@ const SidebarNavigationLink = React.forwardRef((props: ISidebarNavigationLink, r > { menu.push({ to: '/follow_requests', text: intl.formatMessage(messages.follow_requests), - icon: require('@tabler/icons/user-plus.svg'), + icon: require('@tabler/icons/outline/user-plus.svg'), count: followRequestsCount, }); } @@ -51,7 +51,7 @@ const SidebarNavigation = () => { menu.push({ to: '/bookmarks', text: intl.formatMessage(messages.bookmarks), - icon: require('@tabler/icons/bookmark.svg'), + icon: require('@tabler/icons/outline/bookmark.svg'), }); } @@ -59,7 +59,7 @@ const SidebarNavigation = () => { menu.push({ to: '/lists', text: intl.formatMessage(messages.lists), - icon: require('@tabler/icons/list.svg'), + icon: require('@tabler/icons/outline/list.svg'), }); } @@ -67,14 +67,14 @@ const SidebarNavigation = () => { menu.push({ to: '/events', text: intl.formatMessage(messages.events), - icon: require('@tabler/icons/calendar-event.svg'), + icon: require('@tabler/icons/outline/calendar-event.svg'), }); } if (isDeveloper) { menu.push({ to: '/developers', - icon: require('@tabler/icons/code.svg'), + icon: require('@tabler/icons/outline/code.svg'), text: intl.formatMessage(messages.developers), }); } @@ -91,7 +91,7 @@ const SidebarNavigation = () => { return ( } @@ -103,7 +103,7 @@ const SidebarNavigation = () => { return ( } /> ); @@ -117,13 +117,14 @@ const SidebarNavigation = () => { } /> } /> @@ -131,7 +132,8 @@ const SidebarNavigation = () => { <> } /> @@ -141,27 +143,30 @@ const SidebarNavigation = () => { {features.groups && ( } /> )} } /> } /> {account.staff && ( } /> @@ -174,7 +179,8 @@ const SidebarNavigation = () => { {(account || !restrictUnauth.timelines.local) && ( : } /> )} @@ -182,7 +188,7 @@ const SidebarNavigation = () => { {(features.federating && (account || !restrictUnauth.timelines.federated)) && ( } /> )} @@ -192,7 +198,7 @@ const SidebarNavigation = () => { {menu.length > 0 && ( } /> diff --git a/src/components/status-action-bar.tsx b/src/components/status-action-bar.tsx index 0d0de6a1f..2d7628fd3 100644 --- a/src/components/status-action-bar.tsx +++ b/src/components/status-action-bar.tsx @@ -232,7 +232,7 @@ const StatusActionBar: React.FC = ({ dispatch(deleteStatus(status.id, withRedraft)); } else { dispatch(openModal('CONFIRM', { - icon: withRedraft ? require('@tabler/icons/edit.svg') : require('@tabler/icons/trash.svg'), + icon: withRedraft ? require('@tabler/icons/outline/edit.svg') : require('@tabler/icons/outline/trash.svg'), heading: intl.formatMessage(withRedraft ? messages.redraftHeading : messages.deleteHeading), message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage), confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm), @@ -313,7 +313,7 @@ const StatusActionBar: React.FC = ({ const account = status.account; dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/ban.svg'), + icon: require('@tabler/icons/outline/ban.svg'), heading: , message: @{account.acct} }} />, confirm: intl.formatMessage(messages.blockConfirm), @@ -409,7 +409,7 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(messages.open), action: handleOpen, - icon: require('@tabler/icons/arrows-vertical.svg'), + icon: require('@tabler/icons/outline/arrows-vertical.svg'), }); } @@ -417,14 +417,14 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(messages.copy), action: handleCopy, - icon: require('@tabler/icons/clipboard-copy.svg'), + icon: require('@tabler/icons/outline/clipboard-copy.svg'), }); if (features.embeds && account.local) { menu.push({ text: intl.formatMessage(messages.embed), action: handleEmbed, - icon: require('@tabler/icons/share.svg'), + icon: require('@tabler/icons/outline/share.svg'), }); } } @@ -441,7 +441,7 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(status.pinned ? messages.unpinFromGroup : messages.pinToGroup), action: handleGroupPinClick, - icon: status.pinned ? require('@tabler/icons/pinned-off.svg') : require('@tabler/icons/pin.svg'), + icon: status.pinned ? require('@tabler/icons/outline/pinned-off.svg') : require('@tabler/icons/outline/pin.svg'), }); } } @@ -450,7 +450,7 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(status.bookmarked ? messages.unbookmark : messages.bookmark), action: handleBookmarkClick, - icon: status.bookmarked ? require('@tabler/icons/bookmark-off.svg') : require('@tabler/icons/bookmark.svg'), + icon: status.bookmarked ? require('@tabler/icons/outline/bookmark-off.svg') : require('@tabler/icons/outline/bookmark.svg'), }); } @@ -458,7 +458,7 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(messages.external, { domain }), action: handleExternalClick, - icon: require('@tabler/icons/external-link.svg'), + icon: require('@tabler/icons/outline/external-link.svg'), }); } @@ -467,7 +467,7 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: handleConversationMuteClick, - icon: mutingConversation ? require('@tabler/icons/bell.svg') : require('@tabler/icons/bell-off.svg'), + icon: mutingConversation ? require('@tabler/icons/outline/bell.svg') : require('@tabler/icons/outline/bell-off.svg'), }); menu.push(null); @@ -477,14 +477,14 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(status.pinned ? messages.unpin : messages.pin), action: handlePinClick, - icon: status.pinned ? require('@tabler/icons/pinned-off.svg') : require('@tabler/icons/pin.svg'), + icon: status.pinned ? require('@tabler/icons/outline/pinned-off.svg') : require('@tabler/icons/outline/pin.svg'), }); } else { if (status.visibility === 'private') { menu.push({ text: intl.formatMessage(status.reblogged ? messages.cancel_reblog_private : messages.reblog_private), action: handleReblogClick, - icon: require('@tabler/icons/repeat.svg'), + icon: require('@tabler/icons/outline/repeat.svg'), }); } } @@ -492,20 +492,20 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(messages.delete), action: handleDeleteClick, - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), destructive: true, }); if (features.editStatuses) { menu.push({ text: intl.formatMessage(messages.edit), action: handleEditClick, - icon: require('@tabler/icons/edit.svg'), + icon: require('@tabler/icons/outline/edit.svg'), }); } else { menu.push({ text: intl.formatMessage(messages.redraft), action: handleRedraftClick, - icon: require('@tabler/icons/edit.svg'), + icon: require('@tabler/icons/outline/edit.svg'), destructive: true, }); } @@ -513,20 +513,20 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(messages.mention, { name: username }), action: handleMentionClick, - icon: require('@tabler/icons/at.svg'), + icon: require('@tabler/icons/outline/at.svg'), }); if (status.account.pleroma?.accepts_chat_messages === true) { menu.push({ text: intl.formatMessage(messages.chat, { name: username }), action: handleChatClick, - icon: require('@tabler/icons/messages.svg'), + icon: require('@tabler/icons/outline/messages.svg'), }); } else if (features.privacyScopes) { menu.push({ text: intl.formatMessage(messages.direct, { name: username }), action: handleDirectClick, - icon: require('@tabler/icons/mail.svg'), + icon: require('@tabler/icons/outline/mail.svg'), }); } @@ -534,7 +534,7 @@ const StatusActionBar: React.FC = ({ if (features.groupsMuting && status.group) { menu.push({ text: isMutingGroup ? intl.formatMessage(messages.unmuteGroup) : intl.formatMessage(messages.muteGroup), - icon: require('@tabler/icons/volume-3.svg'), + icon: require('@tabler/icons/outline/volume-3.svg'), action: isMutingGroup ? handleUnmuteGroupClick : handleMuteGroupClick, }); menu.push(null); @@ -543,17 +543,17 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(messages.mute, { name: username }), action: handleMuteClick, - icon: require('@tabler/icons/volume-3.svg'), + icon: require('@tabler/icons/outline/volume-3.svg'), }); menu.push({ text: intl.formatMessage(messages.block, { name: username }), action: handleBlockClick, - icon: require('@tabler/icons/ban.svg'), + icon: require('@tabler/icons/outline/ban.svg'), }); menu.push({ text: intl.formatMessage(messages.report, { name: username }), action: handleReport, - icon: require('@tabler/icons/flag.svg'), + icon: require('@tabler/icons/outline/flag.svg'), }); } @@ -575,7 +575,7 @@ const StatusActionBar: React.FC = ({ menu.push({ text: 'Ban from Group', action: handleBlockFromGroup, - icon: require('@tabler/icons/ban.svg'), + icon: require('@tabler/icons/outline/ban.svg'), destructive: true, }); } @@ -584,7 +584,7 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(messages.groupModDelete), action: handleDeleteFromGroup, - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), destructive: true, }); } @@ -596,28 +596,28 @@ const StatusActionBar: React.FC = ({ menu.push({ text: intl.formatMessage(messages.adminAccount, { name: username }), action: onModerate, - icon: require('@tabler/icons/gavel.svg'), + icon: require('@tabler/icons/outline/gavel.svg'), }); if (isAdmin) { menu.push({ text: intl.formatMessage(messages.admin_status), href: `/pleroma/admin/#/statuses/${status.id}/`, - icon: require('@tabler/icons/pencil.svg'), + icon: require('@tabler/icons/outline/pencil.svg'), }); } menu.push({ text: intl.formatMessage(status.sensitive === false ? messages.markStatusSensitive : messages.markStatusNotSensitive), action: handleToggleStatusSensitivity, - icon: require('@tabler/icons/alert-triangle.svg'), + icon: require('@tabler/icons/outline/alert-triangle.svg'), }); if (!ownAccount) { menu.push({ text: intl.formatMessage(messages.deleteStatus), action: handleDeleteStatus, - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), destructive: true, }); } @@ -655,14 +655,14 @@ const StatusActionBar: React.FC = ({ const meEmojiTitle = intl.formatMessage(reactMessages[meEmojiName || ''] || messages.favourite); const menu = _makeMenu(publicStatus); - let reblogIcon = require('@tabler/icons/repeat.svg'); + let reblogIcon = require('@tabler/icons/outline/repeat.svg'); let replyTitle; let replyDisabled = false; if (status.visibility === 'direct') { - reblogIcon = require('@tabler/icons/mail.svg'); + reblogIcon = require('@tabler/icons/outline/mail.svg'); } else if (status.visibility === 'private') { - reblogIcon = require('@tabler/icons/lock.svg'); + reblogIcon = require('@tabler/icons/outline/lock.svg'); } if ((status.group as Group)?.membership_required && !groupRelationship?.member) { @@ -673,11 +673,11 @@ const StatusActionBar: React.FC = ({ const reblogMenu = [{ text: intl.formatMessage(status.reblogged ? messages.cancel_reblog_private : messages.reblog), action: handleReblogClick, - icon: require('@tabler/icons/repeat.svg'), + icon: require('@tabler/icons/outline/repeat.svg'), }, { text: intl.formatMessage(messages.quotePost), action: handleQuoteClick, - icon: require('@tabler/icons/quote.svg'), + icon: require('@tabler/icons/outline/quote.svg'), }]; const reblogButton = ( @@ -726,7 +726,7 @@ const StatusActionBar: React.FC = ({ > = ({ = ({ ) : ( = ({ {features.dislikes && ( = ({ {(acceptsZaps && window.webln) && ( = ({ {canShare && ( @@ -814,7 +814,7 @@ const StatusActionBar: React.FC = ({ diff --git a/src/components/status-content.tsx b/src/components/status-content.tsx index c69459106..3302239f4 100644 --- a/src/components/status-content.tsx +++ b/src/components/status-content.tsx @@ -27,7 +27,7 @@ interface IReadMoreButton { const ReadMoreButton: React.FC = ({ onClick }) => ( ); diff --git a/src/components/status.tsx b/src/components/status.tsx index e94755262..507e499f5 100644 --- a/src/components/status.tsx +++ b/src/components/status.tsx @@ -210,7 +210,7 @@ const Status: React.FC = (props) => { return ( } + icon={} text={ = (props) => { return ( } + icon={} text={ = (props) => { return ( } + icon={} text={ } @@ -287,7 +287,7 @@ const Status: React.FC = (props) => { return ( } + icon={} text={ {intl.formatMessage(messages.contact)} @@ -151,7 +151,7 @@ const SensitiveContentOverlay = React.forwardRef {intl.formatMessage(messages.show)} @@ -160,7 +160,7 @@ const SensitiveContentOverlay = React.forwardRef ) : null}
diff --git a/src/components/thumb-navigation-link.tsx b/src/components/thumb-navigation-link.tsx index a8176fb1d..f824392e5 100644 --- a/src/components/thumb-navigation-link.tsx +++ b/src/components/thumb-navigation-link.tsx @@ -9,13 +9,14 @@ interface IThumbNavigationLink { count?: number; countMax?: number; src: string; + activeSrc?: string; text: string | React.ReactElement; to: string; exact?: boolean; paths?: Array; } -const ThumbNavigationLink: React.FC = ({ count, countMax, src, text, to, exact, paths }): JSX.Element => { +const ThumbNavigationLink: React.FC = ({ count, countMax, src, activeSrc, text, to, exact, paths }): JSX.Element => { const { pathname } = useLocation(); const isActive = (): boolean => { @@ -28,11 +29,13 @@ const ThumbNavigationLink: React.FC = ({ count, countMax, const active = isActive(); + const icon = (active && activeSrc) || src; + return ( {count !== undefined ? ( = ({ count, countMax, /> ) : ( { if (features.chats) { return ( } to='/chats' exact @@ -33,7 +33,8 @@ const ThumbNavigation: React.FC = (): JSX.Element => { if (features.directTimeline || features.conversations) { return ( } to='/messages' paths={['/messages', '/conversations']} @@ -47,7 +48,8 @@ const ThumbNavigation: React.FC = (): JSX.Element => { return (
} to='/' exact @@ -55,7 +57,8 @@ const ThumbNavigation: React.FC = (): JSX.Element => { {features.groups && ( } to={groupsPath} exact @@ -63,7 +66,7 @@ const ThumbNavigation: React.FC = (): JSX.Element => { )} } to='/search' exact @@ -71,7 +74,8 @@ const ThumbNavigation: React.FC = (): JSX.Element => { {account && ( } to='/notifications' exact @@ -83,7 +87,7 @@ const ThumbNavigation: React.FC = (): JSX.Element => { {(account && account.staff) && ( } to='/soapbox/admin' count={dashboardCount} diff --git a/src/components/translate-button.tsx b/src/components/translate-button.tsx index 7a9c31976..57752ec28 100644 --- a/src/components/translate-button.tsx +++ b/src/components/translate-button.tsx @@ -53,7 +53,7 @@ const TranslateButton: React.FC = ({ status }) => {
diff --git a/src/components/ui/accordion/accordion.tsx b/src/components/ui/accordion/accordion.tsx index 7e959c227..efaa02a69 100644 --- a/src/components/ui/accordion/accordion.tsx +++ b/src/components/ui/accordion/accordion.tsx @@ -60,7 +60,7 @@ const Accordion: React.FC = ({ headline, children, menu, expanded = {menu && ( )} {action && actionIcon && ( @@ -72,7 +72,7 @@ const Accordion: React.FC = ({ headline, children, menu, expanded = )} diff --git a/src/components/ui/avatar/avatar.tsx b/src/components/ui/avatar/avatar.tsx index d00f8ebf2..448ab7e52 100644 --- a/src/components/ui/avatar/avatar.tsx +++ b/src/components/ui/avatar/avatar.tsx @@ -35,7 +35,7 @@ const Avatar = (props: IAvatar) => { className={clsx('flex items-center justify-center rounded-full bg-gray-200 dark:bg-gray-900', className)} > diff --git a/src/components/ui/card/card.tsx b/src/components/ui/card/card.tsx index 7da58e758..a4bb389a1 100644 --- a/src/components/ui/card/card.tsx +++ b/src/components/ui/card/card.tsx @@ -72,7 +72,7 @@ const CardHeader: React.FC = ({ className, children, backHref, onBa return ( - + {intl.formatMessage(messages.back)} ); diff --git a/src/components/ui/carousel/carousel.tsx b/src/components/ui/carousel/carousel.tsx index da94f30d9..0bece264c 100644 --- a/src/components/ui/carousel/carousel.tsx +++ b/src/components/ui/carousel/carousel.tsx @@ -68,7 +68,7 @@ const Carousel: React.FC = (props): JSX.Element => { disabled={!hasPrevPage || isDisabled} > @@ -100,7 +100,7 @@ const Carousel: React.FC = (props): JSX.Element => { disabled={!hasNextPage || isDisabled} > diff --git a/src/components/ui/emoji-selector/emoji-selector.tsx b/src/components/ui/emoji-selector/emoji-selector.tsx index 2876aa0a4..114f94d96 100644 --- a/src/components/ui/emoji-selector/emoji-selector.tsx +++ b/src/components/ui/emoji-selector/emoji-selector.tsx @@ -134,7 +134,7 @@ const EmojiSelector: React.FC = ({ {all && ( )} diff --git a/src/components/ui/icon/svg-icon.test.tsx b/src/components/ui/icon/svg-icon.test.tsx index 8dc01be21..bd8c0a81b 100644 --- a/src/components/ui/icon/svg-icon.test.tsx +++ b/src/components/ui/icon/svg-icon.test.tsx @@ -1,4 +1,4 @@ -import IconCode from '@tabler/icons/code.svg'; +import IconCode from '@tabler/icons/outline/code.svg'; import React from 'react'; import { render, screen } from 'soapbox/jest/test-helpers'; diff --git a/src/components/ui/input/input.tsx b/src/components/ui/input/input.tsx index e1a069dd0..9d23b62a2 100644 --- a/src/components/ui/input/input.tsx +++ b/src/components/ui/input/input.tsx @@ -123,7 +123,7 @@ const Input = React.forwardRef( className='h-full px-2 text-gray-700 hover:text-gray-500 focus:ring-2 focus:ring-primary-500 dark:text-gray-600 dark:hover:text-gray-400' > diff --git a/src/components/ui/modal/modal.tsx b/src/components/ui/modal/modal.tsx index 5d17d6f67..8747cc4f0 100644 --- a/src/components/ui/modal/modal.tsx +++ b/src/components/ui/modal/modal.tsx @@ -65,7 +65,7 @@ const Modal = React.forwardRef(({ cancelAction, cancelText, children, - closeIcon = require('@tabler/icons/x.svg'), + closeIcon = require('@tabler/icons/outline/x.svg'), closePosition = 'right', confirmationAction, confirmationDisabled, @@ -107,7 +107,7 @@ const Modal = React.forwardRef(({ > {onBack && ( { children: Iterable; + full?: boolean; } /** Multiple-select dropdown. */ const Select = React.forwardRef((props, ref) => { - const { children, className, ...filteredProps } = props; + const { children, className, full = true, ...filteredProps } = props; return ( + + {instance.domain} + + )} + {...props} + /> + ); +}; + +export default EditIdentity; \ No newline at end of file diff --git a/src/features/edit-profile/components/avatar-picker.tsx b/src/features/edit-profile/components/avatar-picker.tsx index ab06c522c..a973ec302 100644 --- a/src/features/edit-profile/components/avatar-picker.tsx +++ b/src/features/edit-profile/components/avatar-picker.tsx @@ -43,7 +43,7 @@ const AvatarPicker = React.forwardRef(({ classNam })} > diff --git a/src/features/edit-profile/components/header-picker.tsx b/src/features/edit-profile/components/header-picker.tsx index 3176876c6..fd60e79c6 100644 --- a/src/features/edit-profile/components/header-picker.tsx +++ b/src/features/edit-profile/components/header-picker.tsx @@ -55,7 +55,7 @@ const HeaderPicker = React.forwardRef(({ src, onC justifyContent='center' > @@ -76,7 +76,7 @@ const HeaderPicker = React.forwardRef(({ src, onC {onClear && src && ( { type='text' value={data.nip05} onChange={handleTextChange('nip05')} - placeholder={intl.formatMessage(messages.nip05Placeholder, { domain: location.host })} + placeholder={intl.formatMessage(messages.nip05Placeholder, { domain: instance.domain })} /> )} diff --git a/src/features/emoji/containers/emoji-picker-dropdown-container.tsx b/src/features/emoji/containers/emoji-picker-dropdown-container.tsx index af662f7ad..51ade8de2 100644 --- a/src/features/emoji/containers/emoji-picker-dropdown-container.tsx +++ b/src/features/emoji/containers/emoji-picker-dropdown-container.tsx @@ -40,7 +40,7 @@ const EmojiPickerDropdownContainer = ( 'text-gray-600 hover:text-gray-700 dark:hover:text-gray-500': true, })} ref={refs.setReference} - src={require('@tabler/icons/mood-happy.svg')} + src={require('@tabler/icons/outline/mood-happy.svg')} title={title} aria-label={title} aria-expanded={visible} diff --git a/src/features/event/components/event-action-button.tsx b/src/features/event/components/event-action-button.tsx index a3fb6f9d9..413942eed 100644 --- a/src/features/event/components/event-action-button.tsx +++ b/src/features/event/components/event-action-button.tsx @@ -70,14 +70,14 @@ const EventActionButton: React.FC = ({ status, theme = 'secondary' switch (event.join_state) { case 'accept': buttonLabel = ; - buttonIcon = require('@tabler/icons/check.svg'); + buttonIcon = require('@tabler/icons/outline/check.svg'); break; case 'pending': buttonLabel = ; break; case 'reject': buttonLabel = ; - buttonIcon = require('@tabler/icons/ban.svg'); + buttonIcon = require('@tabler/icons/outline/ban.svg'); buttonDisabled = true; break; default: diff --git a/src/features/event/components/event-date.tsx b/src/features/event/components/event-date.tsx index 081b79c9a..978f49213 100644 --- a/src/features/event/components/event-date.tsx +++ b/src/features/event/components/event-date.tsx @@ -50,7 +50,7 @@ const EventDate: React.FC = ({ status }) => { return ( - + {date} ); diff --git a/src/features/event/components/event-header.tsx b/src/features/event/components/event-header.tsx index 78aad74eb..6d09147fb 100644 --- a/src/features/event/components/event-header.tsx +++ b/src/features/event/components/event-header.tsx @@ -140,7 +140,7 @@ const EventHeader: React.FC = ({ status }) => { const handleDeleteClick = () => { dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), heading: intl.formatMessage(messages.deleteHeading), message: intl.formatMessage(messages.deleteMessage), confirm: intl.formatMessage(messages.deleteConfirm), @@ -166,7 +166,7 @@ const EventHeader: React.FC = ({ status }) => { const handleBlockClick = () => { dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/ban.svg'), + icon: require('@tabler/icons/outline/ban.svg'), heading: , message: @{account.acct} }} />, confirm: intl.formatMessage(messages.blockConfirm), @@ -206,12 +206,12 @@ const EventHeader: React.FC = ({ status }) => { { text: intl.formatMessage(messages.exportIcs), action: handleExportClick, - icon: require('@tabler/icons/calendar-plus.svg'), + icon: require('@tabler/icons/outline/calendar-plus.svg'), }, { text: intl.formatMessage(messages.copy), action: handleCopy, - icon: require('@tabler/icons/link.svg'), + icon: require('@tabler/icons/outline/link.svg'), }, ]; @@ -219,7 +219,7 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(messages.external, { domain }), action: handleExternalClick, - icon: require('@tabler/icons/external-link.svg'), + icon: require('@tabler/icons/outline/external-link.svg'), }); } @@ -229,7 +229,7 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(status.bookmarked ? messages.unbookmark : messages.bookmark), action: handleBookmarkClick, - icon: status.bookmarked ? require('@tabler/icons/bookmark-off.svg') : require('@tabler/icons/bookmark.svg'), + icon: status.bookmarked ? require('@tabler/icons/outline/bookmark-off.svg') : require('@tabler/icons/outline/bookmark.svg'), }); } @@ -237,14 +237,14 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(status.reblogged ? messages.unreblog : messages.reblog), action: handleReblogClick, - icon: require('@tabler/icons/repeat.svg'), + icon: require('@tabler/icons/outline/repeat.svg'), }); if (features.quotePosts) { menu.push({ text: intl.formatMessage(messages.quotePost), action: handleQuoteClick, - icon: require('@tabler/icons/quote.svg'), + icon: require('@tabler/icons/outline/quote.svg'), }); } } @@ -256,34 +256,34 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(status.pinned ? messages.unpin : messages.pin), action: handlePinClick, - icon: status.pinned ? require('@tabler/icons/pinned-off.svg') : require('@tabler/icons/pin.svg'), + icon: status.pinned ? require('@tabler/icons/outline/pinned-off.svg') : require('@tabler/icons/outline/pin.svg'), }); } menu.push({ text: intl.formatMessage(messages.delete), action: handleDeleteClick, - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), destructive: true, }); } else { menu.push({ text: intl.formatMessage(messages.mention, { name: username }), action: handleMentionClick, - icon: require('@tabler/icons/at.svg'), + icon: require('@tabler/icons/outline/at.svg'), }); if (status.getIn(['account', 'pleroma', 'accepts_chat_messages']) === true) { menu.push({ text: intl.formatMessage(messages.chat, { name: username }), action: handleChatClick, - icon: require('@tabler/icons/messages.svg'), + icon: require('@tabler/icons/outline/messages.svg'), }); } else if (features.privacyScopes) { menu.push({ text: intl.formatMessage(messages.direct, { name: username }), action: handleDirectClick, - icon: require('@tabler/icons/mail.svg'), + icon: require('@tabler/icons/outline/mail.svg'), }); } @@ -291,17 +291,17 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(messages.mute, { name: username }), action: handleMuteClick, - icon: require('@tabler/icons/circle-x.svg'), + icon: require('@tabler/icons/outline/circle-x.svg'), }); menu.push({ text: intl.formatMessage(messages.block, { name: username }), action: handleBlockClick, - icon: require('@tabler/icons/ban.svg'), + icon: require('@tabler/icons/outline/ban.svg'), }); menu.push({ text: intl.formatMessage(messages.report, { name: username }), action: handleReport, - icon: require('@tabler/icons/flag.svg'), + icon: require('@tabler/icons/outline/flag.svg'), }); } @@ -311,28 +311,28 @@ const EventHeader: React.FC = ({ status }) => { menu.push({ text: intl.formatMessage(messages.adminAccount, { name: account.username }), action: handleModerate, - icon: require('@tabler/icons/gavel.svg'), + icon: require('@tabler/icons/outline/gavel.svg'), }); if (isAdmin) { menu.push({ text: intl.formatMessage(messages.adminStatus), action: handleModerateStatus, - icon: require('@tabler/icons/pencil.svg'), + icon: require('@tabler/icons/outline/pencil.svg'), }); } menu.push({ text: intl.formatMessage(status.sensitive === false ? messages.markStatusSensitive : messages.markStatusNotSensitive), action: handleToggleStatusSensitivity, - icon: require('@tabler/icons/alert-triangle.svg'), + icon: require('@tabler/icons/outline/alert-triangle.svg'), }); if (account.id !== ownAccount?.id) { menu.push({ text: intl.formatMessage(messages.deleteStatus), action: handleDeleteStatus, - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), destructive: true, }); } @@ -381,7 +381,7 @@ const EventHeader: React.FC = ({ status }) => { = ({ status }) => { - + = ({ status }) => { - + = ({ status }) => { {event.location && ( - + {event.location.get('name')} diff --git a/src/features/event/event-information.tsx b/src/features/event/event-information.tsx index 11f6b9cb1..d84d6096b 100644 --- a/src/features/event/event-information.tsx +++ b/src/features/event/event-information.tsx @@ -102,7 +102,7 @@ const EventInformation: React.FC = ({ params }) => { - + {text} @@ -125,7 +125,7 @@ const EventInformation: React.FC = ({ params }) => { - + = ({ params }) => { {status.event.links.map(link => ( - + {(link.remote_url || link.url).replace(/^https?:\/\//, '')} diff --git a/src/features/events/components/event-carousel.tsx b/src/features/events/components/event-carousel.tsx index fe8225115..e6e25f604 100644 --- a/src/features/events/components/event-carousel.tsx +++ b/src/features/events/components/event-carousel.tsx @@ -59,7 +59,7 @@ const EventCarousel: React.FC = ({ statusIds, isLoading, emptyMe onClick={() => handleChangeIndex(index - 1)} className='flex h-8 w-8 items-center justify-center rounded-full bg-white/50 backdrop-blur dark:bg-gray-900/50' > - + )} @@ -72,7 +72,7 @@ const EventCarousel: React.FC = ({ statusIds, isLoading, emptyMe onClick={() => handleChangeIndex(index + 1)} className='flex h-8 w-8 items-center justify-center rounded-full bg-white/50 backdrop-blur dark:bg-gray-900/50' > - + )} diff --git a/src/features/federation-restrictions/components/instance-restrictions.tsx b/src/features/federation-restrictions/components/instance-restrictions.tsx index 344dc766d..d33aa5a85 100644 --- a/src/features/federation-restrictions/components/instance-restrictions.tsx +++ b/src/features/federation-restrictions/components/instance-restrictions.tsx @@ -53,7 +53,7 @@ const InstanceRestrictions: React.FC = ({ remoteInstance if (followers_only) { items.push(( - + = ({ remoteInstance )); } else if (federated_timeline_removal) { items.push(( - + = ({ remoteInstance if (fullMediaRemoval) { items.push(( - + = ({ remoteInstance )); } else if (partialMediaRemoval) { items.push(( - + = ({ remoteInstance if (!fullMediaRemoval && media_nsfw) { items.push(( - + = ({ remoteInstance if (remoteInstance.federation.reject === true) { return ( - + = ({ remoteInstance } else if (hasRestrictions(remoteInstance)) { return ( <> - + = ({ remoteInstance ); } else { return ( - + = ({ host }) => { return ( diff --git a/src/features/group/components/group-header.tsx b/src/features/group/components/group-header.tsx index 21eb7e5dd..de70bc237 100644 --- a/src/features/group/components/group-header.tsx +++ b/src/features/group/components/group-header.tsx @@ -112,7 +112,7 @@ const GroupHeader: React.FC = ({ group }) => { className='flex h-32 w-full items-center justify-center bg-gray-200 md:rounded-t-xl lg:h-52 dark:bg-gray-800/30' > {isHeaderMissing ? ( - + ) : header} ); diff --git a/src/features/group/components/group-member-list-item.tsx b/src/features/group/components/group-member-list-item.tsx index 79be5ef50..eea6514f8 100644 --- a/src/features/group/components/group-member-list-item.tsx +++ b/src/features/group/components/group-member-list-item.tsx @@ -138,13 +138,13 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => { if (isMemberUser) { items.push({ text: intl.formatMessage(messages.groupModPromoteMod, { role: GroupRoles.ADMIN }), - icon: require('@tabler/icons/briefcase.svg'), + icon: require('@tabler/icons/outline/briefcase.svg'), action: handleAdminAssignment, }); } else if (isMemberAdmin) { items.push({ text: intl.formatMessage(messages.groupModDemote, { role: GroupRoles.ADMIN, name: account.username }), - icon: require('@tabler/icons/briefcase.svg'), + icon: require('@tabler/icons/outline/briefcase.svg'), action: handleUserAssignment, destructive: true, }); @@ -159,14 +159,14 @@ const GroupMemberListItem = (props: IGroupMemberListItem) => { if (features.groupsKick) { items.push({ text: intl.formatMessage(messages.groupModKick, { name: account.username }), - icon: require('@tabler/icons/user-minus.svg'), + icon: require('@tabler/icons/outline/user-minus.svg'), action: handleKickFromGroup, }); } items.push({ text: intl.formatMessage(messages.groupModBlock, { name: account.username }), - icon: require('@tabler/icons/ban.svg'), + icon: require('@tabler/icons/outline/ban.svg'), action: handleBlockFromGroup, destructive: true, }); diff --git a/src/features/group/components/group-options-button.tsx b/src/features/group/components/group-options-button.tsx index 6b35d03d7..c52bc1eaa 100644 --- a/src/features/group/components/group-options-button.tsx +++ b/src/features/group/components/group-options-button.tsx @@ -98,7 +98,7 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => { if (canShare) { items.push({ text: intl.formatMessage(messages.share), - icon: require('@tabler/icons/share.svg'), + icon: require('@tabler/icons/outline/share.svg'), action: handleShare, }); } @@ -106,7 +106,7 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => { if (isInGroup) { items.push({ text: isMuting ? intl.formatMessage(messages.unmute) : intl.formatMessage(messages.mute), - icon: require('@tabler/icons/volume-3.svg'), + icon: require('@tabler/icons/outline/volume-3.svg'), action: isMuting ? handleUnmute : handleMute, }); } @@ -114,7 +114,7 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => { if (isMember || isAdmin) { items.push({ text: intl.formatMessage(messages.report), - icon: require('@tabler/icons/flag.svg'), + icon: require('@tabler/icons/outline/flag.svg'), action: () => dispatch(initReport(ReportableEntities.GROUP, account as Account, { group })), }); } @@ -123,7 +123,7 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => { items.push(null); items.push({ text: intl.formatMessage(messages.leave), - icon: require('@tabler/icons/logout.svg'), + icon: require('@tabler/icons/outline/logout.svg'), action: handleLeave, }); } @@ -138,7 +138,7 @@ const GroupOptionsButton = ({ group }: IGroupActionButton) => { return ( ( @@ -49,8 +49,8 @@ const GroupPrivacy = ({ group }: IGroupPolicy) => ( className='h-4 w-4' src={ group.locked - ? require('@tabler/icons/lock.svg') - : require('@tabler/icons/world.svg') + ? require('@tabler/icons/outline/lock.svg') + : require('@tabler/icons/outline/world.svg') } /> diff --git a/src/features/group/components/group-relationship.tsx b/src/features/group/components/group-relationship.tsx index 51782f46b..ff6e5ee5c 100644 --- a/src/features/group/components/group-relationship.tsx +++ b/src/features/group/components/group-relationship.tsx @@ -28,8 +28,8 @@ const GroupRelationship = ({ group }: IGroupRelationship) => { className='h-4 w-4' src={ isOwner - ? require('@tabler/icons/users.svg') - : require('@tabler/icons/gavel.svg') + ? require('@tabler/icons/outline/users.svg') + : require('@tabler/icons/outline/gavel.svg') } /> diff --git a/src/features/group/components/group-tag-list-item.tsx b/src/features/group/components/group-tag-list-item.tsx index 38db498b9..45a5dc82f 100644 --- a/src/features/group/components/group-tag-list-item.tsx +++ b/src/features/group/components/group-tag-list-item.tsx @@ -87,7 +87,7 @@ const GroupTagListItem = (props: IGroupMemberListItem) => { if (!isOwner && tag.pinned) { return ( @@ -112,8 +112,8 @@ const GroupTagListItem = (props: IGroupMemberListItem) => { theme='transparent' src={ tag.pinned ? - require('@tabler/icons/pin-filled.svg') : - require('@tabler/icons/pin.svg') + require('@tabler/icons/filled/pin.svg') : + require('@tabler/icons/outline/pin.svg') } iconClassName='h-5 w-5 text-primary-500 dark:text-accent-blue' data-testid='pin-icon' @@ -128,7 +128,7 @@ const GroupTagListItem = (props: IGroupMemberListItem) => { @@ -181,8 +181,8 @@ const GroupTagListItem = (props: IGroupMemberListItem) => { theme='transparent' src={ tag.visible ? - require('@tabler/icons/eye.svg') : - require('@tabler/icons/eye-off.svg') + require('@tabler/icons/outline/eye.svg') : + require('@tabler/icons/outline/eye-off.svg') } iconClassName='h-5 w-5 text-primary-500 dark:text-accent-blue' /> diff --git a/src/features/group/edit-group.tsx b/src/features/group/edit-group.tsx index b34eca26e..aa80d7ce5 100644 --- a/src/features/group/edit-group.tsx +++ b/src/features/group/edit-group.tsx @@ -115,7 +115,7 @@ const EditGroup: React.FC = ({ params: { groupId } }) => { placeholder={intl.formatMessage(messages.groupNamePlaceholder)} maxLength={maxName} {...displayName} - append={} + append={} disabled /> diff --git a/src/features/group/group-tag-timeline.tsx b/src/features/group/group-tag-timeline.tsx index 02b7d9aca..085302b66 100644 --- a/src/features/group/group-tag-timeline.tsx +++ b/src/features/group/group-tag-timeline.tsx @@ -50,7 +50,7 @@ const GroupTagTimeline: React.FC = (props) => {
diff --git a/src/features/group/group-tags.tsx b/src/features/group/group-tags.tsx index e3b65b5f4..fcc37798f 100644 --- a/src/features/group/group-tags.tsx +++ b/src/features/group/group-tags.tsx @@ -41,7 +41,7 @@ const GroupTopics: React.FC = (props) => {
diff --git a/src/features/group/group-timeline.tsx b/src/features/group/group-timeline.tsx index e1d11f0e3..d30506b6a 100644 --- a/src/features/group/group-timeline.tsx +++ b/src/features/group/group-timeline.tsx @@ -110,7 +110,7 @@ const GroupTimeline: React.FC = (props) => {
diff --git a/src/features/group/manage-group.tsx b/src/features/group/manage-group.tsx index c669c026f..1fa02f174 100644 --- a/src/features/group/manage-group.tsx +++ b/src/features/group/manage-group.tsx @@ -62,7 +62,7 @@ const ManageGroup: React.FC = ({ params }) => { const onDeleteGroup = () => dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), heading: intl.formatMessage(messages.deleteHeading), message: intl.formatMessage(messages.deleteMessage), confirm: intl.formatMessage(messages.deleteConfirm), diff --git a/src/features/groups/components/discover/group-list-item.tsx b/src/features/groups/components/discover/group-list-item.tsx index f092c3a20..a101a45cd 100644 --- a/src/features/groups/components/discover/group-list-item.tsx +++ b/src/features/groups/components/discover/group-list-item.tsx @@ -39,7 +39,7 @@ const GroupListItem = (props: IGroupListItem) => { diff --git a/src/features/groups/components/discover/layout-buttons.tsx b/src/features/groups/components/discover/layout-buttons.tsx index 7e116408f..fce0ad711 100644 --- a/src/features/groups/components/discover/layout-buttons.tsx +++ b/src/features/groups/components/discover/layout-buttons.tsx @@ -20,7 +20,7 @@ const LayoutButtons = ({ layout, onSelect }: ILayoutButtons) => ( onClick={() => onSelect(GroupLayout.LIST)} > ( onClick={() => onSelect(GroupLayout.GRID)} > {
diff --git a/src/features/groups/discover.tsx b/src/features/groups/discover.tsx index f91c3ca48..0bb5af179 100644 --- a/src/features/groups/discover.tsx +++ b/src/features/groups/discover.tsx @@ -36,7 +36,7 @@ const Discover: React.FC = () => { {isSearching ? ( { append={ + + + +
+ + + ); +}; + +export default NostrRelays; diff --git a/src/features/nostr/hooks/useNostrReq.ts b/src/features/nostr/hooks/useNostrReq.ts index 654c814f3..72e1187ac 100644 --- a/src/features/nostr/hooks/useNostrReq.ts +++ b/src/features/nostr/hooks/useNostrReq.ts @@ -1,14 +1,17 @@ -import { NostrEvent, NostrFilter } from '@soapbox/nspec'; +import { NSet, NostrEvent, NostrFilter } from '@soapbox/nspec'; import isEqual from 'lodash/isEqual'; import { useEffect, useRef, useState } from 'react'; import { useNostr } from 'soapbox/contexts/nostr-context'; +import { useForceUpdate } from 'soapbox/hooks/useForceUpdate'; /** Streams events from the relay for the given filters. */ export function useNostrReq(filters: NostrFilter[]): { events: NostrEvent[]; eose: boolean; closed: boolean } { const { relay } = useNostr(); - const [events, setEvents] = useState([]); + const nset = useRef(new NSet()); + const forceUpdate = useForceUpdate(); + const [closed, setClosed] = useState(false); const [eose, setEose] = useState(false); @@ -21,7 +24,8 @@ export function useNostrReq(filters: NostrFilter[]): { events: NostrEvent[]; eos (async () => { for await (const msg of relay.req(value, { signal })) { if (msg[0] === 'EVENT') { - setEvents((prev) => [msg[2], ...prev]); + nset.current.add(msg[2]); + forceUpdate(); } else if (msg[0] === 'EOSE') { setEose(true); } else if (msg[0] === 'CLOSED') { @@ -41,7 +45,7 @@ export function useNostrReq(filters: NostrFilter[]): { events: NostrEvent[]; eos }, [relay, value]); return { - events, + events: [...nset.current], eose, closed, }; diff --git a/src/features/notifications/components/filter-bar.tsx b/src/features/notifications/components/filter-bar.tsx index 5ed194b6a..45f67d884 100644 --- a/src/features/notifications/components/filter-bar.tsx +++ b/src/features/notifications/components/filter-bar.tsx @@ -46,43 +46,43 @@ const NotificationFilterBar = () => { }); } else { items.push({ - text: , + text: , title: intl.formatMessage(messages.mentions), action: onClick('mention'), name: 'mention', }); items.push({ - text: , + text: , title: intl.formatMessage(messages.favourites), action: onClick('favourite'), name: 'favourite', }); if (features.emojiReacts) items.push({ - text: , + text: , title: intl.formatMessage(messages.emoji_reacts), action: onClick('pleroma:emoji_reaction'), name: 'pleroma:emoji_reaction', }); items.push({ - text: , + text: , title: intl.formatMessage(messages.boosts), action: onClick('reblog'), name: 'reblog', }); items.push({ - text: , + text: , title: intl.formatMessage(messages.polls), action: onClick('poll'), name: 'poll', }); items.push({ - text: , + text: , title: intl.formatMessage(messages.statuses), action: onClick('status'), name: 'status', }); items.push({ - text: , + text: , title: intl.formatMessage(messages.follows), action: onClick('follow'), name: 'follow', diff --git a/src/features/notifications/components/notification.tsx b/src/features/notifications/components/notification.tsx index fbefbf44f..7a05a7d23 100644 --- a/src/features/notifications/components/notification.tsx +++ b/src/features/notifications/components/notification.tsx @@ -39,23 +39,23 @@ const buildLink = (account: AccountEntity): JSX.Element => ( ); const icons: Record = { - follow: require('@tabler/icons/user-plus.svg'), - follow_request: require('@tabler/icons/user-plus.svg'), - mention: require('@tabler/icons/at.svg'), - favourite: require('@tabler/icons/heart.svg'), - group_favourite: require('@tabler/icons/heart.svg'), - reblog: require('@tabler/icons/repeat.svg'), - group_reblog: require('@tabler/icons/repeat.svg'), - status: require('@tabler/icons/bell-ringing.svg'), - poll: require('@tabler/icons/chart-bar.svg'), - move: require('@tabler/icons/briefcase.svg'), - 'pleroma:chat_mention': require('@tabler/icons/messages.svg'), - 'pleroma:emoji_reaction': require('@tabler/icons/mood-happy.svg'), - user_approved: require('@tabler/icons/user-plus.svg'), - update: require('@tabler/icons/pencil.svg'), - 'pleroma:event_reminder': require('@tabler/icons/calendar-time.svg'), - 'pleroma:participation_request': require('@tabler/icons/calendar-event.svg'), - 'pleroma:participation_accepted': require('@tabler/icons/calendar-event.svg'), + follow: require('@tabler/icons/outline/user-plus.svg'), + follow_request: require('@tabler/icons/outline/user-plus.svg'), + mention: require('@tabler/icons/outline/at.svg'), + favourite: require('@tabler/icons/outline/heart.svg'), + group_favourite: require('@tabler/icons/outline/heart.svg'), + reblog: require('@tabler/icons/outline/repeat.svg'), + group_reblog: require('@tabler/icons/outline/repeat.svg'), + status: require('@tabler/icons/outline/bell-ringing.svg'), + poll: require('@tabler/icons/outline/chart-bar.svg'), + move: require('@tabler/icons/outline/briefcase.svg'), + 'pleroma:chat_mention': require('@tabler/icons/outline/messages.svg'), + 'pleroma:emoji_reaction': require('@tabler/icons/outline/mood-happy.svg'), + user_approved: require('@tabler/icons/outline/user-plus.svg'), + update: require('@tabler/icons/outline/pencil.svg'), + 'pleroma:event_reminder': require('@tabler/icons/outline/calendar-time.svg'), + 'pleroma:participation_request': require('@tabler/icons/outline/calendar-event.svg'), + 'pleroma:participation_accepted': require('@tabler/icons/outline/calendar-event.svg'), }; const nameMessage = defineMessage({ diff --git a/src/features/onboarding/steps/avatar-selection-step.tsx b/src/features/onboarding/steps/avatar-selection-step.tsx index 149d5e3e3..2c2af64bb 100644 --- a/src/features/onboarding/steps/avatar-selection-step.tsx +++ b/src/features/onboarding/steps/avatar-selection-step.tsx @@ -90,7 +90,7 @@ const AvatarSelectionStep = ({ onNext }: { onNext: () => void }) => { })} disabled={isSubmitting} > - + diff --git a/src/features/onboarding/steps/completed-step.tsx b/src/features/onboarding/steps/completed-step.tsx index 082defb4d..813eff22a 100644 --- a/src/features/onboarding/steps/completed-step.tsx +++ b/src/features/onboarding/steps/completed-step.tsx @@ -7,7 +7,7 @@ const CompletedStep = ({ onComplete }: { onComplete: () => void }) => ( - + diff --git a/src/features/onboarding/steps/cover-photo-selection-step.tsx b/src/features/onboarding/steps/cover-photo-selection-step.tsx index 1e1c0107b..b09b89f6a 100644 --- a/src/features/onboarding/steps/cover-photo-selection-step.tsx +++ b/src/features/onboarding/steps/cover-photo-selection-step.tsx @@ -103,7 +103,7 @@ const CoverPhotoSelectionStep = ({ onNext }: { onNext: () => void }) => { })} disabled={isSubmitting} > - + diff --git a/src/features/onboarding/steps/fediverse-step.tsx b/src/features/onboarding/steps/fediverse-step.tsx index 87afc3680..c66f34eb7 100644 --- a/src/features/onboarding/steps/fediverse-step.tsx +++ b/src/features/onboarding/steps/fediverse-step.tsx @@ -13,7 +13,7 @@ const FediverseStep = ({ onNext }: { onNext: () => void }) => { - + { } action={dismissExplanationBox} - actionIcon={require('@tabler/icons/x.svg')} + actionIcon={require('@tabler/icons/outline/x.svg')} actionLabel={intl.formatMessage(messages.dismiss)} expanded={explanationBoxExpanded} onToggle={toggleExplanationBox} diff --git a/src/features/remote-timeline/components/pinned-hosts-picker.tsx b/src/features/remote-timeline/components/pinned-hosts-picker.tsx index 2777aa6e3..16cd45481 100644 --- a/src/features/remote-timeline/components/pinned-hosts-picker.tsx +++ b/src/features/remote-timeline/components/pinned-hosts-picker.tsx @@ -16,7 +16,7 @@ const PinnedHostsPicker: React.FC = ({ host: activeHost }) = return ( - {pinnedHosts.map((host: any) => ( + {pinnedHosts.map((host) => ( ); }; diff --git a/src/features/scheduled-statuses/components/scheduled-status.tsx b/src/features/scheduled-statuses/components/scheduled-status.tsx index 7243bffd4..6e71f7cbe 100644 --- a/src/features/scheduled-statuses/components/scheduled-status.tsx +++ b/src/features/scheduled-statuses/components/scheduled-status.tsx @@ -5,7 +5,7 @@ import Account from 'soapbox/components/account'; import AttachmentThumbs from 'soapbox/components/attachment-thumbs'; import StatusContent from 'soapbox/components/status-content'; import StatusReplyMentions from 'soapbox/components/status-reply-mentions'; -import { HStack } from 'soapbox/components/ui'; +import { HStack, Stack } from 'soapbox/components/ui'; import PollPreview from 'soapbox/features/ui/components/poll-preview'; import { useAppSelector } from 'soapbox/hooks'; @@ -40,28 +40,28 @@ const ScheduledStatus: React.FC = ({ statusId, ...other }) => account={account} timestamp={status.created_at} futureTimestamp - hideActions + action={} /> - - - {status.media_attachments.size > 0 && ( - + - )} - {status.poll && } + {status.media_attachments.size > 0 && ( + + )} - + {status.poll && } + ); diff --git a/src/features/scheduled-statuses/index.tsx b/src/features/scheduled-statuses/index.tsx index 781a06759..0a9b3dcae 100644 --- a/src/features/scheduled-statuses/index.tsx +++ b/src/features/scheduled-statuses/index.tsx @@ -39,6 +39,7 @@ const ScheduledStatuses = () => { isLoading={typeof isLoading === 'boolean' ? isLoading : true} onLoadMore={() => handleLoadMore(dispatch)} emptyMessage={emptyMessage} + listClassName='divide-y divide-solid divide-gray-200 dark:divide-gray-800' > {statusIds.map((id: string) => )} diff --git a/src/features/settings/index.tsx b/src/features/settings/index.tsx index 434445c4e..f2e53b867 100644 --- a/src/features/settings/index.tsx +++ b/src/features/settings/index.tsx @@ -20,6 +20,8 @@ const messages = defineMessages({ configureMfa: { id: 'settings.configure_mfa', defaultMessage: 'Configure MFA' }, deleteAccount: { id: 'settings.delete_account', defaultMessage: 'Delete Account' }, editProfile: { id: 'settings.edit_profile', defaultMessage: 'Edit Profile' }, + editIdentity: { id: 'settings.edit_identity', defaultMessage: 'Identity' }, + editRelays: { id: 'nostr_relays.title', defaultMessage: 'Relays' }, exportData: { id: 'column.export_data', defaultMessage: 'Export data' }, importData: { id: 'navigation_bar.import_data', defaultMessage: 'Import data' }, mfaDisabled: { id: 'mfa.disabled', defaultMessage: 'Disabled' }, @@ -65,6 +67,12 @@ const Settings = () => { {displayName} + {features.nip05 && ( + + {account?.source?.nostr?.nip05} + + )} + {features.nostr && } diff --git a/src/features/soapbox-config/components/site-preview.tsx b/src/features/soapbox-config/components/site-preview.tsx index 617dc3121..82e201e4f 100644 --- a/src/features/soapbox-config/components/site-preview.tsx +++ b/src/features/soapbox-config/components/site-preview.tsx @@ -39,11 +39,11 @@ const SitePreview: React.FC = ({ soapbox }) => { -
+
-
= ({ avatarSize={42} icon={ } @@ -109,9 +109,9 @@ const DetailedStatus: React.FC = ({ } if (actualStatus.visibility === 'direct') { - statusTypeIcon = ; + statusTypeIcon = ; } else if (actualStatus.visibility === 'private') { - statusTypeIcon = ; + statusTypeIcon = ; } return ( diff --git a/src/features/theme-editor/index.tsx b/src/features/theme-editor/index.tsx index e6c624b35..66604a109 100644 --- a/src/features/theme-editor/index.tsx +++ b/src/features/theme-editor/index.tsx @@ -208,15 +208,15 @@ const ThemeEditor: React.FC = () => { items={[{ text: intl.formatMessage(messages.restore), action: restoreDefaultTheme, - icon: require('@tabler/icons/refresh.svg'), + icon: require('@tabler/icons/outline/refresh.svg'), }, { text: intl.formatMessage(messages.import), action: importTheme, - icon: require('@tabler/icons/upload.svg'), + icon: require('@tabler/icons/outline/upload.svg'), }, { text: intl.formatMessage(messages.export), action: exportTheme, - icon: require('@tabler/icons/download.svg'), + icon: require('@tabler/icons/outline/download.svg'), }]} /> @@ -74,7 +74,7 @@ const GroupFAB: React.FC = () => { diff --git a/src/features/ui/components/instance-info-panel.tsx b/src/features/ui/components/instance-info-panel.tsx index 16093516f..26a52df84 100644 --- a/src/features/ui/components/instance-info-panel.tsx +++ b/src/features/ui/components/instance-info-panel.tsx @@ -41,7 +41,7 @@ const InstanceInfoPanel: React.FC = ({ host }) => { ); diff --git a/src/features/ui/components/instance-moderation-panel.tsx b/src/features/ui/components/instance-moderation-panel.tsx index cd9055a21..75cb34b05 100644 --- a/src/features/ui/components/instance-moderation-panel.tsx +++ b/src/features/ui/components/instance-moderation-panel.tsx @@ -35,7 +35,7 @@ const InstanceModerationPanel: React.FC = ({ host }) = return [{ text: intl.formatMessage(messages.editFederation), action: handleEditFederation, - icon: require('@tabler/icons/edit.svg'), + icon: require('@tabler/icons/outline/edit.svg'), }]; }; @@ -45,7 +45,7 @@ const InstanceModerationPanel: React.FC = ({ host }) = } action={account?.admin ? ( - + ) : undefined} > diff --git a/src/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx b/src/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx index 2e7bcdb7e..76ea614d9 100644 --- a/src/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx +++ b/src/features/ui/components/modals/account-moderation-modal/account-moderation-modal.tsx @@ -172,7 +172,7 @@ const AccountModerationModal: React.FC = ({ onClose, ac {features.adminFE && ( - diff --git a/src/features/ui/components/modals/boost-modal.tsx b/src/features/ui/components/modals/boost-modal.tsx index df7d530e4..bc4d73177 100644 --- a/src/features/ui/components/modals/boost-modal.tsx +++ b/src/features/ui/components/modals/boost-modal.tsx @@ -38,7 +38,7 @@ const BoostModal: React.FC = ({ status, onReblog, onClose }) => { - Shift + }} /> + Shift + }} /> diff --git a/src/features/ui/components/modals/compose-event-modal/compose-event-modal.tsx b/src/features/ui/components/modals/compose-event-modal/compose-event-modal.tsx index 0e25d4119..8f20ce69c 100644 --- a/src/features/ui/components/modals/compose-event-modal/compose-event-modal.tsx +++ b/src/features/ui/components/modals/compose-event-modal/compose-event-modal.tsx @@ -137,7 +137,7 @@ const ComposeEventModal: React.FC = ({ onClose }) => { dispatch((dispatch, getState) => { if (checkEventComposeContent(getState().compose_event)) { dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), heading: id ? : , @@ -177,12 +177,12 @@ const ComposeEventModal: React.FC = ({ onClose }) => { const renderLocation = () => location && ( - + {location.description} {[location.street, location.locality, location.country].filter(val => val?.trim()).join(' · ')} - onChangeLocation(null)} /> + onChangeLocation(null)} /> ); @@ -213,7 +213,7 @@ const ComposeEventModal: React.FC = ({ onClose }) => { {banner ? ( <> - + ) : ( diff --git a/src/features/ui/components/modals/compose-event-modal/upload-button.tsx b/src/features/ui/components/modals/compose-event-modal/upload-button.tsx index be9f59818..ab377d62f 100644 --- a/src/features/ui/components/modals/compose-event-modal/upload-button.tsx +++ b/src/features/ui/components/modals/compose-event-modal/upload-button.tsx @@ -28,7 +28,7 @@ const UploadButton: React.FC = ({ disabled, onSelectFile }) => { return ( diff --git a/src/features/ui/components/modals/compose-modal.tsx b/src/features/ui/components/modals/compose-modal.tsx index 83e471475..b5fc73c33 100644 --- a/src/features/ui/components/modals/compose-modal.tsx +++ b/src/features/ui/components/modals/compose-modal.tsx @@ -36,7 +36,7 @@ const ComposeModal: React.FC = ({ onClose, composeId = 'compose-m const onClickClose = () => { if (checkComposeContent(compose)) { dispatch(openModal('CONFIRM', { - icon: require('@tabler/icons/trash.svg'), + icon: require('@tabler/icons/outline/trash.svg'), heading: statusId ? : , diff --git a/src/features/ui/components/modals/edit-bookmark-folder-modal.tsx b/src/features/ui/components/modals/edit-bookmark-folder-modal.tsx index 0acb130d5..e2a407829 100644 --- a/src/features/ui/components/modals/edit-bookmark-folder-modal.tsx +++ b/src/features/ui/components/modals/edit-bookmark-folder-modal.tsx @@ -58,7 +58,7 @@ const EmojiPicker: React.FC = ({ emoji, emojiUrl, ...props }) => { > {emoji ? - : } + : } {createPortal( diff --git a/src/features/ui/components/modals/event-map-modal.tsx b/src/features/ui/components/modals/event-map-modal.tsx index 5000c8fa7..2a16a84f3 100644 --- a/src/features/ui/components/modals/event-map-modal.tsx +++ b/src/features/ui/components/modals/event-map-modal.tsx @@ -64,7 +64,7 @@ const EventMapModal: React.FC = ({ onClose, statusId }) => { >
- diff --git a/src/features/ui/components/modals/landing-page-modal.tsx b/src/features/ui/components/modals/landing-page-modal.tsx index 8b451257d..cdb3c9bb8 100644 --- a/src/features/ui/components/modals/landing-page-modal.tsx +++ b/src/features/ui/components/modals/landing-page-modal.tsx @@ -38,7 +38,7 @@ const LandingPageModal: React.FC = ({ onClose }) => { target='_blank' className='flex items-center space-x-3 rounded-md p-3 hover:bg-gray-50 dark:hover:bg-gray-900/50' > - + {intl.formatMessage(messages.helpCenter)} diff --git a/src/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx b/src/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx index f9a032398..86972b83a 100644 --- a/src/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx +++ b/src/features/ui/components/modals/manage-group-modal/steps/confirmation-step.tsx @@ -101,12 +101,12 @@ const ConfirmationStep: React.FC = ({ group }) => { {('share' in navigator) && ( - )} - diff --git a/src/features/ui/components/modals/media-modal.tsx b/src/features/ui/components/modals/media-modal.tsx index 6f78a8ed5..fe30f7247 100644 --- a/src/features/ui/components/modals/media-modal.tsx +++ b/src/features/ui/components/modals/media-modal.tsx @@ -255,7 +255,7 @@ const MediaModal: React.FC = (props) => { > = (props) => { = (props) => { {status && ( = (props) => { onClick={handlePrevClick} aria-label={intl.formatMessage(messages.previous)} > - +
)} @@ -318,7 +318,7 @@ const MediaModal: React.FC = (props) => { onClick={handleNextClick} aria-label={intl.formatMessage(messages.next)} > - +
)} diff --git a/src/features/ui/components/modals/nostr-signup-modal/steps/keygen-step.tsx b/src/features/ui/components/modals/nostr-signup-modal/steps/keygen-step.tsx index 4fe7869c2..83d604fa7 100644 --- a/src/features/ui/components/modals/nostr-signup-modal/steps/keygen-step.tsx +++ b/src/features/ui/components/modals/nostr-signup-modal/steps/keygen-step.tsx @@ -53,7 +53,7 @@ const KeygenStep: React.FC = ({ onClose }) => { - diff --git a/src/features/ui/components/modals/reply-mentions-modal.tsx b/src/features/ui/components/modals/reply-mentions-modal.tsx index bb21d99ac..69ae41acd 100644 --- a/src/features/ui/components/modals/reply-mentions-modal.tsx +++ b/src/features/ui/components/modals/reply-mentions-modal.tsx @@ -33,7 +33,7 @@ const ReplyMentionsModal: React.FC = ({ composeId, onClose } onClose={onClickClose} - closeIcon={require('@tabler/icons/arrow-left.svg')} + closeIcon={require('@tabler/icons/outline/arrow-left.svg')} closePosition='left' >
diff --git a/src/features/ui/components/modals/report-modal/report-modal.tsx b/src/features/ui/components/modals/report-modal/report-modal.tsx index ea242e940..ce961d0fb 100644 --- a/src/features/ui/components/modals/report-modal/report-modal.tsx +++ b/src/features/ui/components/modals/report-modal/report-modal.tsx @@ -226,7 +226,7 @@ const ReportModal = ({ onClose }: IReportModal) => { } + label={} > {intl.formatMessage(messages.reportContext)} diff --git a/src/features/ui/components/modals/report-modal/steps/other-actions-step.tsx b/src/features/ui/components/modals/report-modal/steps/other-actions-step.tsx index 9db7a3bc1..8aaf7734c 100644 --- a/src/features/ui/components/modals/report-modal/steps/other-actions-step.tsx +++ b/src/features/ui/components/modals/report-modal/steps/other-actions-step.tsx @@ -65,7 +65,7 @@ const OtherActionsStep = ({ account }: IOtherActionsStep) => {
@@ -562,7 +562,7 @@ const Video: React.FC = ({ className='player-button' onClick={toggleFullscreen} > - +
diff --git a/src/hooks/useForceUpdate.ts b/src/hooks/useForceUpdate.ts new file mode 100644 index 000000000..50a84a468 --- /dev/null +++ b/src/hooks/useForceUpdate.ts @@ -0,0 +1,11 @@ +import { useState, useCallback } from 'react'; + +export function useForceUpdate(): () => void { + const [, setState] = useState(false); + + const forceUpdate = useCallback(() => { + setState(prevState => !prevState); + }, []); + + return forceUpdate; +} diff --git a/src/locales/en.json b/src/locales/en.json index 687c9910b..b28752dca 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -643,6 +643,7 @@ "edit_profile.fields.meta_fields_label": "Profile fields", "edit_profile.fields.nip05_label": "Username", "edit_profile.fields.nip05_placeholder": "user@{domain}", + "edit_profile.fields.nip05_unverified": "Name could not be verified and won't be used.", "edit_profile.fields.stranger_notifications_label": "Block notifications from strangers", "edit_profile.fields.website_label": "Website", "edit_profile.fields.website_placeholder": "Display a Link", @@ -1124,6 +1125,10 @@ "new_group_panel.title": "Create Group", "nostr_extension.found": "Sign in with browser extension.", "nostr_extension.not_found": "Browser extension not found.", + "nostr_relays.read_only": "Read-only", + "nostr_relays.read_write": "Read & write", + "nostr_relays.title": "Relays", + "nostr_relays.write_only": "Write-only", "nostr_signup.key-add.title": "Import Key", "nostr_signup.key.title": "You need a key to continue", "nostr_signup.keygen.title": "Your new key", @@ -1386,6 +1391,7 @@ "settings.change_password": "Change Password", "settings.configure_mfa": "Configure MFA", "settings.delete_account": "Delete Account", + "settings.edit_identity": "Identity", "settings.edit_profile": "Edit Profile", "settings.messages.label": "Allow users to start a new chat with you", "settings.mutes": "Mutes", @@ -1595,6 +1601,8 @@ "upload_error.video_duration_limit": "Video exceeds the current duration limit ({limit, plural, one {# second} other {# seconds}})", "upload_error.video_size_limit": "Video exceeds the current file size limit ({limit})", "upload_form.description": "Describe for the visually impaired", + "upload_form.description_missing.indicator": "Alt", + "upload_form.description_missing.title": "This attachment doesn't have a description", "upload_form.preview": "Preview", "upload_form.undo": "Delete", "upload_progress.label": "Uploading…", diff --git a/src/pages/group-page.tsx b/src/pages/group-page.tsx index ab7bf6469..e2fbfccdd 100644 --- a/src/pages/group-page.tsx +++ b/src/pages/group-page.tsx @@ -34,7 +34,7 @@ const DeletedBlankslate = () => (
@@ -52,7 +52,7 @@ const PrivacyBlankslate = () => (
@@ -70,7 +70,7 @@ const BlockedBlankslate = ({ group }: { group: Group }) => (
diff --git a/src/reducers/compose.ts b/src/reducers/compose.ts index b9f064998..624ea0b3a 100644 --- a/src/reducers/compose.ts +++ b/src/reducers/compose.ts @@ -54,6 +54,7 @@ import { COMPOSE_EDITOR_STATE_SET, COMPOSE_SET_GROUP_TIMELINE_VISIBLE, ComposeAction, + COMPOSE_CHANGE_MEDIA_ORDER, } from '../actions/compose'; import { EVENT_COMPOSE_CANCEL, EVENT_FORM_SET, type EventsAction } from '../actions/events'; import { ME_FETCH_SUCCESS, ME_PATCH_SUCCESS, MeAction } from '../actions/me'; @@ -520,6 +521,14 @@ export default function compose(state = initialState, action: ComposeAction | Ev return updateCompose(state, 'event-compose-modal', compose => compose.set('text', '')); case EVENT_FORM_SET: return updateCompose(state, 'event-compose-modal', compose => compose.set('text', action.text)); + case COMPOSE_CHANGE_MEDIA_ORDER: + return updateCompose(state, action.id, compose => compose.update('media_attachments', list => { + const indexA = list.findIndex(x => x.get('id') === action.a); + const moveItem = list.get(indexA)!; + const indexB = list.findIndex(x => x.get('id') === action.b); + + return list.splice(indexA, 1).splice(indexB, 0, moveItem); + })); default: return state; } diff --git a/src/utils/features.ts b/src/utils/features.ts index 37c7af53b..8c42da8f4 100644 --- a/src/utils/features.ts +++ b/src/utils/features.ts @@ -757,6 +757,9 @@ const getInstanceFeatures = (instance: Instance) => { */ nip05: v.software === DITTO, + /** Has a Nostr relay. */ + nostr: !!instance.nostr?.relay, + /** * Ability to sign Nostr events over websocket. * @see GET /api/v1/streaming?stream=nostr diff --git a/yarn.lock b/yarn.lock index c4ed986bf..4d82d447b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2312,10 +2312,10 @@ dependencies: defer-to-connect "^2.0.0" -"@tabler/icons@^2.0.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-2.4.0.tgz#34b1b0d818dc00926b956c3424bff48b89a5b439" - integrity sha512-JZY9Kk3UsQoqp7Rw/BuWw1PrkRwv5h0psjJBbj+Cn9UVyhdzr5vztg2mywXBAJ+jFBUL/pjnVcIvOzKFw4CXng== +"@tabler/icons@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@tabler/icons/-/icons-3.1.0.tgz#d69d184eae572db6adb452b511562442133cc26d" + integrity sha512-CpZGyS1IVJKFcv88yZ2sYZIpWWhQ6oy76BQKQ5SF0fGgOqgyqKdBGG/YGyyMW632on37MX7VqQIMTzN/uQqmFg== "@tailwindcss/aspect-ratio@^0.4.2": version "0.4.2"