-
-
-
- }
- hintText={}
- >
-
-
-
- }
- hintText={}
- >
-
-
-
+
= ({ accountId }) => {
);
};
-const FeedSuggestions = () => {
+interface IFeedSuggesetions {
+ statusId: string
+ onMoveUp?: (statusId: string, featured?: boolean) => void
+ onMoveDown?: (statusId: string, featured?: boolean) => void
+}
+
+const FeedSuggestions: React.FC = ({ statusId, onMoveUp, onMoveDown }) => {
const intl = useIntl();
const suggestedProfiles = useAppSelector((state) => state.suggestions.items);
const isLoading = useAppSelector((state) => state.suggestions.isLoading);
if (!isLoading && suggestedProfiles.size === 0) return null;
+ const handleHotkeyMoveUp = (e?: KeyboardEvent): void => {
+ if (onMoveUp) {
+ onMoveUp(statusId);
+ }
+ };
+
+ const handleHotkeyMoveDown = (e?: KeyboardEvent): void => {
+ if (onMoveDown) {
+ onMoveDown(statusId);
+ }
+ };
+
+ const handlers = {
+ moveUp: handleHotkeyMoveUp,
+ moveDown: handleHotkeyMoveDown,
+ };
+
return (
-
-
-
+
+
+
+
-
- {intl.formatMessage(messages.viewAll)}
-
-
-
-
-
- {suggestedProfiles.slice(0, 4).map((suggestedProfile) => (
-
- ))}
+
+ {intl.formatMessage(messages.viewAll)}
+
-
-
+
+
+
+ {suggestedProfiles.slice(0, 4).map((suggestedProfile) => (
+
+ ))}
+
+
+
+
);
};
diff --git a/app/soapbox/features/followed_tags/index.tsx b/app/soapbox/features/followed-tags/index.tsx
similarity index 100%
rename from app/soapbox/features/followed_tags/index.tsx
rename to app/soapbox/features/followed-tags/index.tsx
diff --git a/app/soapbox/features/group/edit-group.tsx b/app/soapbox/features/group/edit-group.tsx
index 82f4841b40..94bbee1e1a 100644
--- a/app/soapbox/features/group/edit-group.tsx
+++ b/app/soapbox/features/group/edit-group.tsx
@@ -8,8 +8,9 @@ import { useImageField, useTextField } from 'soapbox/hooks/forms';
import toast from 'soapbox/toast';
import { isDefaultAvatar, isDefaultHeader } from 'soapbox/utils/accounts';
-import AvatarPicker from './components/group-avatar-picker';
-import HeaderPicker from './components/group-header-picker';
+import AvatarPicker from '../edit-profile/components/avatar-picker';
+import HeaderPicker from '../edit-profile/components/header-picker';
+
import GroupTagsField from './components/group-tags-field';
import type { List as ImmutableList } from 'immutable';
@@ -60,8 +61,8 @@ const EditGroup: React.FC = ({ params: { groupId } }) => {
await updateGroup({
display_name: displayName.value,
note: note.value,
- avatar: avatar.file,
- header: header.file,
+ avatar: avatar.file === null ? '' : avatar.file,
+ header: header.file === null ? '' : header.file,
tags,
}, {
onSuccess() {
diff --git a/app/soapbox/features/status/components/thread.tsx b/app/soapbox/features/status/components/thread.tsx
index 058f02a083..9a9e5fe8c4 100644
--- a/app/soapbox/features/status/components/thread.tsx
+++ b/app/soapbox/features/status/components/thread.tsx
@@ -122,6 +122,9 @@ const Thread = (props: IThread) => {
};
});
+ let initialTopMostItemIndex = ancestorsIds.size;
+ if (!useWindowScroll && initialTopMostItemIndex !== 0) initialTopMostItemIndex = ancestorsIds.size + 1;
+
const [showMedia, setShowMedia] = useState(status?.visibility === 'self' ? false : defaultMediaVisibility(status, displayMedia));
const node = useRef(null);
@@ -263,15 +266,12 @@ const Thread = (props: IThread) => {
};
const _selectChild = (index: number) => {
+ if (!useWindowScroll) index = index + 1;
scroller.current?.scrollIntoView({
index,
behavior: 'smooth',
done: () => {
- const element = document.querySelector(`#thread [data-index="${index}"] .focusable`);
-
- if (element) {
- element.focus();
- }
+ node.current?.querySelector(`[data-index="${index}"] .focusable`)?.focus();
},
});
};
@@ -410,7 +410,7 @@ const Thread = (props: IThread) => {
if (!useWindowScroll) {
// Add padding to the top of the Thread (for Media Modal)
- children.push();
+ children.push();
}
if (hasAncestors) {
@@ -447,7 +447,7 @@ const Thread = (props: IThread) => {
hasMore={!!next}
onLoadMore={handleLoadMore}
placeholderComponent={() => }
- initialTopMostItemIndex={ancestorsIds.size}
+ initialTopMostItemIndex={initialTopMostItemIndex}
useWindowScroll={useWindowScroll}
itemClassName={itemClassName}
className={
@@ -465,4 +465,4 @@ const Thread = (props: IThread) => {
);
};
-export default Thread;
\ No newline at end of file
+export default Thread;
diff --git a/app/soapbox/features/ui/components/link-footer.tsx b/app/soapbox/features/ui/components/link-footer.tsx
index 402f49e97d..a056f23322 100644
--- a/app/soapbox/features/ui/components/link-footer.tsx
+++ b/app/soapbox/features/ui/components/link-footer.tsx
@@ -48,6 +48,9 @@ const LinkFooter: React.FC = (): JSX.Element => {
{(features.filters || features.filtersV2) && (
)}
+ {features.followedHashtagsList && (
+
+ )}
{features.federating && (
)}
diff --git a/app/soapbox/features/ui/components/modals/manage-group-modal/steps/details-step.tsx b/app/soapbox/features/ui/components/modals/manage-group-modal/steps/details-step.tsx
index 02dbf3279f..0bf6fc3250 100644
--- a/app/soapbox/features/ui/components/modals/manage-group-modal/steps/details-step.tsx
+++ b/app/soapbox/features/ui/components/modals/manage-group-modal/steps/details-step.tsx
@@ -3,8 +3,8 @@ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { CreateGroupParams, useGroupValidation } from 'soapbox/api/hooks';
import { Form, FormGroup, Input, Textarea } from 'soapbox/components/ui';
-import AvatarPicker from 'soapbox/features/group/components/group-avatar-picker';
-import HeaderPicker from 'soapbox/features/group/components/group-header-picker';
+import AvatarPicker from 'soapbox/features/edit-profile/components/avatar-picker';
+import HeaderPicker from 'soapbox/features/edit-profile/components/header-picker';
import GroupTagsField from 'soapbox/features/group/components/group-tags-field';
import { useAppSelector, useDebounce, useInstance } from 'soapbox/hooks';
import { usePreview } from 'soapbox/hooks/forms';
@@ -66,6 +66,8 @@ const DetailsStep: React.FC = ({ params, onChange }) => {
};
};
+ const handleImageClear = (property: keyof CreateGroupParams) => () => onChange({ [property]: undefined });
+
const handleTagsChange = (tags: string[]) => {
onChange({
...params,
@@ -92,7 +94,7 @@ const DetailsStep: React.FC = ({ params, onChange }) => {
return (