diff --git a/app/soapbox/actions/notifications.ts b/app/soapbox/actions/notifications.ts index 4edd76c22..db8fd688f 100644 --- a/app/soapbox/actions/notifications.ts +++ b/app/soapbox/actions/notifications.ts @@ -11,7 +11,7 @@ import { getFilters, regexFromFilters } from 'soapbox/selectors'; import { isLoggedIn } from 'soapbox/utils/auth'; import { getFeatures, parseVersion, PLEROMA } from 'soapbox/utils/features'; import { unescapeHTML } from 'soapbox/utils/html'; -import { NOTIFICATION_TYPES } from 'soapbox/utils/notification'; +import { EXCLUDE_TYPES, NOTIFICATION_TYPES } from 'soapbox/utils/notification'; import { joinPublicPath } from 'soapbox/utils/static'; import { fetchRelationships } from './accounts'; @@ -195,7 +195,9 @@ const expandNotifications = ({ maxId }: Record = {}, done: () => an if (activeFilter === 'all') { if (features.notificationsIncludeTypes) { - params.types = NOTIFICATION_TYPES; + params.types = NOTIFICATION_TYPES.filter(type => !EXCLUDE_TYPES.includes(type as any)); + } else { + params.exclude_types = EXCLUDE_TYPES; } } else { if (features.notificationsIncludeTypes) { diff --git a/app/soapbox/components/ui/hstack/hstack.tsx b/app/soapbox/components/ui/hstack/hstack.tsx index a109da608..996320dea 100644 --- a/app/soapbox/components/ui/hstack/hstack.tsx +++ b/app/soapbox/components/ui/hstack/hstack.tsx @@ -40,6 +40,8 @@ interface IHStack { space?: keyof typeof spaces /** Whether to let the flexbox grow. */ grow?: boolean + /** HTML element to use for container. */ + element?: keyof JSX.IntrinsicElements, /** Extra CSS styles for the
*/ style?: React.CSSProperties /** Whether to let the flexbox wrap onto multiple lines. */ @@ -48,10 +50,12 @@ interface IHStack { /** Horizontal row of child elements. */ const HStack = forwardRef((props, ref) => { - const { space, alignItems, grow, justifyContent, wrap, className, ...filteredProps } = props; + const { space, alignItems, justifyContent, className, grow, element = 'div', wrap, ...filteredProps } = props; + + const Elem = element as 'div'; return ( -
{ - /** Size of the gap between elements. */ - space?: keyof typeof spaces /** Horizontal alignment of children. */ alignItems?: keyof typeof alignItemsOptions + /** Extra class names on the element. */ + className?: string /** Vertical alignment of children. */ justifyContent?: keyof typeof justifyContentOptions - /** Extra class names on the
element. */ - className?: string + /** Size of the gap between elements. */ + space?: keyof typeof spaces /** Whether to let the flexbox grow. */ grow?: boolean + /** HTML element to use for container. */ + element?: keyof JSX.IntrinsicElements, } /** Vertical stack of child elements. */ const Stack = React.forwardRef((props, ref: React.LegacyRef | undefined) => { - const { space, alignItems, justifyContent, className, grow, ...filteredProps } = props; + const { space, alignItems, justifyContent, className, grow, element = 'div', ...filteredProps } = props; + + const Elem = element as 'div'; return ( -
= ({ token }) => { +const AuthToken: React.FC = ({ token, isCurrent }) => { const dispatch = useAppDispatch(); const intl = useIntl(); const handleRevoke = () => { - dispatch(revokeOAuthTokenById(token.id)); + if (isCurrent) + dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/alert-triangle.svg'), + heading: intl.formatMessage(messages.revokeSessionHeading), + message: intl.formatMessage(messages.revokeSessionMessage), + confirm: intl.formatMessage(messages.revokeSessionConfirm), + onConfirm: () => { + dispatch(revokeOAuthTokenById(token.id)); + }, + })); + else { + dispatch(revokeOAuthTokenById(token.id)); + } }; return ( @@ -42,7 +61,7 @@ const AuthToken: React.FC = ({ token }) => {
-
@@ -55,6 +74,11 @@ const AuthTokenList: React.FC = () => { const dispatch = useAppDispatch(); const intl = useIntl(); const tokens = useAppSelector(state => state.security.get('tokens').reverse()); + const currentTokenId = useAppSelector(state => { + const currentToken = state.auth.get('tokens').valueSeq().find((token: ImmutableMap) => token.get('me') === state.auth.get('me')); + + return currentToken?.get('id'); + }); useEffect(() => { dispatch(fetchOAuthTokens()); @@ -63,7 +87,7 @@ const AuthTokenList: React.FC = () => { const body = tokens ? (
{tokens.map((token) => ( - + ))}
) : ; diff --git a/app/soapbox/features/compose/components/compose-form.tsx b/app/soapbox/features/compose/components/compose-form.tsx index f9eb98204..e93215aec 100644 --- a/app/soapbox/features/compose/components/compose-form.tsx +++ b/app/soapbox/features/compose/components/compose-form.tsx @@ -132,7 +132,7 @@ const ComposeForm = ({ id, shouldCondense, autoFocus, clickab setComposeFocused(true); }; - const handleSubmit = () => { + const handleSubmit = (e?: React.FormEvent) => { if (text !== autosuggestTextareaRef.current?.textarea?.value) { // Something changed the text inside the textarea (e.g. browser extensions like Grammarly) // Update the state to match the current text @@ -142,6 +142,10 @@ const ComposeForm = ({ id, shouldCondense, autoFocus, clickab // Submit disabled: const fulltext = [spoilerText, countableText(text)].join(''); + if (e) { + e.preventDefault(); + } + if (isSubmitting || isUploading || isChangingUpload || length(fulltext) > maxTootChars || (fulltext.length !== 0 && fulltext.trim().length === 0 && !anyMedia)) { return; } @@ -261,7 +265,7 @@ const ComposeForm = ({ id, shouldCondense, autoFocus, clickab } return ( - + {scheduledStatusCount > 0 && ( ({ id, shouldCondense, autoFocus, clickab
)} -
diff --git a/app/soapbox/features/compose/components/polls/poll-form.tsx b/app/soapbox/features/compose/components/polls/poll-form.tsx index 4daf54048..e61f1975f 100644 --- a/app/soapbox/features/compose/components/polls/poll-form.tsx +++ b/app/soapbox/features/compose/components/polls/poll-form.tsx @@ -168,7 +168,7 @@ const PollForm: React.FC = ({ composeId }) => { -
diff --git a/app/soapbox/features/compose/components/spoiler-input.tsx b/app/soapbox/features/compose/components/spoiler-input.tsx index e6f53d04c..873450116 100644 --- a/app/soapbox/features/compose/components/spoiler-input.tsx +++ b/app/soapbox/features/compose/components/spoiler-input.tsx @@ -68,7 +68,7 @@ const SpoilerInput = React.forwardRef(({ />
-
@@ -77,4 +77,4 @@ const SpoilerInput = React.forwardRef(({ ); }); -export default SpoilerInput; \ No newline at end of file +export default SpoilerInput; diff --git a/app/soapbox/features/ui/components/profile-dropdown.tsx b/app/soapbox/features/ui/components/profile-dropdown.tsx index 0a9a3f297..8830515e4 100644 --- a/app/soapbox/features/ui/components/profile-dropdown.tsx +++ b/app/soapbox/features/ui/components/profile-dropdown.tsx @@ -39,6 +39,8 @@ const ProfileDropdown: React.FC = ({ account, children }) => { const features = useFeatures(); const intl = useIntl(); + useAppSelector((state) => console.log(state.auth.toJS())); + const authUsers = useAppSelector((state) => state.auth.get('users')); const otherAccounts = useAppSelector((state) => authUsers.map((authUser: any) => getAccount(state, authUser.get('id')))); diff --git a/app/soapbox/utils/notification.ts b/app/soapbox/utils/notification.ts index 907a97434..49c360b92 100644 --- a/app/soapbox/utils/notification.ts +++ b/app/soapbox/utils/notification.ts @@ -14,6 +14,12 @@ const NOTIFICATION_TYPES = [ 'update', ] as const; +/** Notification types to exclude from the "All" filter by default. */ +const EXCLUDE_TYPES = [ + 'pleroma:chat_mention', + 'chat', // TruthSocial +] as const; + type NotificationType = typeof NOTIFICATION_TYPES[number]; /** Ensure the Notification is a valid, known type. */ @@ -21,6 +27,7 @@ const validType = (type: string): type is NotificationType => NOTIFICATION_TYPES export { NOTIFICATION_TYPES, + EXCLUDE_TYPES, NotificationType, validType, };