diff --git a/app/javascript/flavours/glitch/components/empty_state/empty_state.module.scss b/app/javascript/flavours/glitch/components/empty_state/empty_state.module.scss
index 1707b3bc08..bdab2f2732 100644
--- a/app/javascript/flavours/glitch/components/empty_state/empty_state.module.scss
+++ b/app/javascript/flavours/glitch/components/empty_state/empty_state.module.scss
@@ -10,6 +10,13 @@
}
.content {
+ svg,
+ img {
+ width: 240px;
+ max-width: 100%;
+ margin-bottom: 16px;
+ }
+
h3 {
font-size: 17px;
font-weight: 500;
diff --git a/app/javascript/flavours/glitch/components/empty_state/index.tsx b/app/javascript/flavours/glitch/components/empty_state/index.tsx
index 93f034f3e9..59210bbc87 100644
--- a/app/javascript/flavours/glitch/components/empty_state/index.tsx
+++ b/app/javascript/flavours/glitch/components/empty_state/index.tsx
@@ -9,10 +9,12 @@ import classes from './empty_state.module.scss';
*/
export const EmptyState: React.FC<{
- title?: string | React.ReactElement;
- message?: string | React.ReactElement;
+ image?: React.ReactNode;
+ title?: React.ReactNode;
+ message?: React.ReactNode;
children?: React.ReactNode;
}> = ({
+ image,
title = (
),
@@ -21,10 +23,13 @@ export const EmptyState: React.FC<{
}) => {
return (
-
-
{title}
- {!!message &&
{message}
}
-
+ {(title || message || image) && (
+
+ {image}
+ {!!title &&
{title}
}
+ {!!message &&
{message}
}
+
+ )}
{children}
diff --git a/app/javascript/flavours/glitch/features/account_featured/components/empty_message.tsx b/app/javascript/flavours/glitch/features/account_featured/components/empty_message.tsx
index 1a38022ea6..301283b520 100644
--- a/app/javascript/flavours/glitch/features/account_featured/components/empty_message.tsx
+++ b/app/javascript/flavours/glitch/features/account_featured/components/empty_message.tsx
@@ -1,9 +1,15 @@
import { FormattedMessage } from 'react-intl';
import { useParams } from 'react-router';
+import { Link } from 'react-router-dom';
-import { LimitedAccountHint } from 'flavours/glitch/features/account_timeline/components/limited_account_hint';
-import { me } from 'flavours/glitch/initial_state';
+import { EmptyState } from '@/flavours/glitch/components/empty_state';
+import { LimitedAccountHint } from '@/flavours/glitch/features/account_timeline/components/limited_account_hint';
+import { areCollectionsEnabled } from '@/flavours/glitch/features/collections/utils';
+import { useCurrentAccountId } from '@/flavours/glitch/hooks/useAccountId';
+import { useTheme } from '@/flavours/glitch/hooks/useTheme';
+import ElephantDarkImage from '@/images/elephant_ui_dark.svg?react';
+import ElephantLightImage from '@/images/elephant_ui_light.svg?react';
interface EmptyMessageProps {
suspended: boolean;
@@ -19,21 +25,59 @@ export const EmptyMessage: React.FC = ({
blockedBy,
}) => {
const { acct } = useParams<{ acct?: string }>();
+ const me = useCurrentAccountId();
+ const theme = useTheme();
+ const ElephantImage =
+ theme === 'dark' ? ElephantDarkImage : ElephantLightImage;
+
if (!accountId) {
return null;
}
+ let title: React.ReactNode = null;
let message: React.ReactNode = null;
+ const hasCollections = areCollectionsEnabled();
+
+ const image = ;
+
if (me === accountId) {
- message = (
-
- );
+ if (hasCollections) {
+ // Return only here to insert the "Create a collection" button as the action for the empty state.
+ return (
+
+ }
+ >
+
+
+
+
+ );
+ } else {
+ title = (
+
+ );
+ message = (
+
+ );
+ }
} else if (suspended) {
- message = (
+ title = (
= ({
} else if (hidden) {
message = ;
} else if (blockedBy) {
- message = (
+ title = (
);
- } else if (acct) {
- message = (
-
- );
} else {
- message = (
+ // Standard other account empty state.
+ title = (
);
+ if (hasCollections) {
+ if (acct) {
+ message = (
+
+ );
+ } else {
+ message = (
+
+ );
+ }
+ } else {
+ if (acct) {
+ message = (
+
+ );
+ } else {
+ message = (
+
+ );
+ }
+ }
}
- return (
-
- {message}
-
- );
+ return ;
};
diff --git a/app/javascript/flavours/glitch/features/account_featured/components/featured_tag.tsx b/app/javascript/flavours/glitch/features/account_featured/components/featured_tag.tsx
deleted file mode 100644
index 274a4c10eb..0000000000
--- a/app/javascript/flavours/glitch/features/account_featured/components/featured_tag.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import { defineMessages, useIntl } from 'react-intl';
-
-import type { Map as ImmutableMap } from 'immutable';
-
-import { Hashtag } from 'flavours/glitch/components/hashtag';
-
-export type TagMap = ImmutableMap<
- 'id' | 'name' | 'url' | 'statuses_count' | 'last_status_at' | 'accountId',
- string | null
->;
-
-interface FeaturedTagProps {
- tag: TagMap;
- account: string;
-}
-
-const messages = defineMessages({
- lastStatusAt: {
- id: 'account.featured_tags.last_status_at',
- defaultMessage: 'Last post on {date}',
- },
- empty: {
- id: 'account.featured_tags.last_status_never',
- defaultMessage: 'No posts',
- },
-});
-
-export const FeaturedTag: React.FC = ({ tag, account }) => {
- const intl = useIntl();
- const name = tag.get('name') ?? '';
- const count = Number.parseInt(tag.get('statuses_count') ?? '');
- return (
- 0
- ? intl.formatMessage(messages.lastStatusAt, {
- date: intl.formatDate(tag.get('last_status_at') ?? '', {
- month: 'short',
- day: '2-digit',
- year: 'numeric',
- }),
- })
- : intl.formatMessage(messages.empty)
- }
- />
- );
-};
diff --git a/app/javascript/flavours/glitch/features/account_featured/index.tsx b/app/javascript/flavours/glitch/features/account_featured/index.tsx
index eb420097ee..60e9531318 100644
--- a/app/javascript/flavours/glitch/features/account_featured/index.tsx
+++ b/app/javascript/flavours/glitch/features/account_featured/index.tsx
@@ -8,7 +8,6 @@ import { List as ImmutableList } from 'immutable';
import { useAccount } from '@/flavours/glitch/hooks/useAccount';
import { fetchEndorsedAccounts } from 'flavours/glitch/actions/accounts';
-import { fetchFeaturedTags } from 'flavours/glitch/actions/featured_tags';
import { Account } from 'flavours/glitch/components/account';
import { ColumnBackButton } from 'flavours/glitch/components/column_back_button';
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
@@ -33,8 +32,6 @@ import { CollectionListItem } from '../collections/detail/collection_list_item';
import { areCollectionsEnabled } from '../collections/utils';
import { EmptyMessage } from './components/empty_message';
-import { FeaturedTag } from './components/featured_tag';
-import type { TagMap } from './components/featured_tag';
const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
multiColumn,
@@ -55,26 +52,15 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
useEffect(() => {
if (accountId) {
- void dispatch(fetchFeaturedTags({ accountId }));
void dispatch(fetchEndorsedAccounts({ accountId }));
+
if (areCollectionsEnabled()) {
void dispatch(fetchAccountCollections({ accountId }));
}
}
}, [accountId, dispatch]);
- const isLoading = useAppSelector(
- (state) =>
- !accountId ||
- !!state.user_lists.getIn(['featured_tags', accountId, 'isLoading']),
- );
- const featuredTags = useAppSelector(
- (state) =>
- state.user_lists.getIn(
- ['featured_tags', accountId, 'items'],
- ImmutableList(),
- ) as ImmutableList,
- );
+ const isLoading = !accountId;
const featuredAccountIds = useAppSelector(
(state) =>
state.user_lists.getIn(
@@ -106,13 +92,7 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
);
}
- const noTags = featuredTags.isEmpty();
-
- if (
- noTags &&
- featuredAccountIds.isEmpty() &&
- listedCollections.length === 0
- ) {
+ if (featuredAccountIds.isEmpty() && listedCollections.length === 0) {
return (
= ({
>
)}
- {!noTags && (
- <>
-
-
-
-
- {featuredTags.map((tag, index) => (
-
-
-
- ))}
-
- >
- )}
{!featuredAccountIds.isEmpty() && (
<>
diff --git a/app/javascript/flavours/glitch/features/account_timeline/components/tabs.tsx b/app/javascript/flavours/glitch/features/account_timeline/components/tabs.tsx
index 9d6229d8ba..d37c5db812 100644
--- a/app/javascript/flavours/glitch/features/account_timeline/components/tabs.tsx
+++ b/app/javascript/flavours/glitch/features/account_timeline/components/tabs.tsx
@@ -8,6 +8,8 @@ import { NavLink } from 'react-router-dom';
import { useAccount } from '@/flavours/glitch/hooks/useAccount';
import { useAccountId } from '@/flavours/glitch/hooks/useAccountId';
+import { areCollectionsEnabled } from '../../collections/utils';
+
import classes from './redesign.module.scss';
const isActive: Required['isActive'] = (match, location) =>
@@ -39,7 +41,14 @@ export const AccountTabs: FC = () => {
)}
{show_featured && (
-
+ {areCollectionsEnabled() ? (
+
+ ) : (
+
+ )}
)}
diff --git a/app/javascript/flavours/glitch/hooks/useTheme.ts b/app/javascript/flavours/glitch/hooks/useTheme.ts
new file mode 100644
index 0000000000..9c67efaf58
--- /dev/null
+++ b/app/javascript/flavours/glitch/hooks/useTheme.ts
@@ -0,0 +1,23 @@
+import { useEffect, useState } from 'react';
+
+import { isDarkMode } from '../utils/theme';
+
+export function useTheme() {
+ const [darkMode, setDarkMode] = useState(() => isDarkMode());
+
+ useEffect(() => {
+ const mutationObserver = new MutationObserver(() => {
+ setDarkMode(isDarkMode());
+ });
+ mutationObserver.observe(document.documentElement, {
+ attributes: true,
+ attributeFilter: ['data-color-scheme'],
+ });
+
+ return () => {
+ mutationObserver.disconnect();
+ };
+ }, []);
+
+ return darkMode ? 'dark' : 'light';
+}