{
- {(signedIn || (localLiveFeedAccess === 'public' && remoteLiveFeedAccess === 'public')) && (
+ {(canViewFeed(signedIn, permissions, localLiveFeedAccess) && canViewFeed(signedIn, permissions, remoteLiveFeedAccess)) && (
@@ -187,7 +197,7 @@ const Firehose = ({ feedType, multiColumn }) => {
onLoadMore={handleLoadMore}
trackScroll
scrollKey='firehose'
- emptyMessage={emptyMessage}
+ emptyMessage={canViewSelectedFeed ? emptyMessage : disabledTimelineMessage}
bindToDocument={!multiColumn}
/>
diff --git a/app/javascript/mastodon/features/navigation_panel/index.tsx b/app/javascript/mastodon/features/navigation_panel/index.tsx
index d509bfb6c..446deb1dd 100644
--- a/app/javascript/mastodon/features/navigation_panel/index.tsx
+++ b/app/javascript/mastodon/features/navigation_panel/index.tsx
@@ -42,6 +42,7 @@ import {
me,
} from 'mastodon/initial_state';
import { transientSingleColumn } from 'mastodon/is_mobile';
+import { canViewFeed } from 'mastodon/permissions';
import { selectUnreadNotificationGroupsCount } from 'mastodon/selectors/notifications';
import { useAppSelector, useAppDispatch } from 'mastodon/store';
@@ -194,7 +195,7 @@ export const NavigationPanel: React.FC<{ multiColumn?: boolean }> = ({
multiColumn = false,
}) => {
const intl = useIntl();
- const { signedIn, disabledAccountId } = useIdentity();
+ const { signedIn, permissions, disabledAccountId } = useIdentity();
const location = useLocation();
const showSearch = useBreakpoint('full') && !multiColumn;
@@ -262,13 +263,12 @@ export const NavigationPanel: React.FC<{ multiColumn?: boolean }> = ({
/>
)}
- {(signedIn ||
- localLiveFeedAccess === 'public' ||
- remoteLiveFeedAccess === 'public') && (
+ {(canViewFeed(signedIn, permissions, localLiveFeedAccess) ||
+ canViewFeed(signedIn, permissions, remoteLiveFeedAccess)) && (
+ ) : (
+
+ );
+
return (
}
+ emptyMessage={emptyMessage}
bindToDocument={!multiColumn}
/>
diff --git a/app/javascript/mastodon/initial_state.ts b/app/javascript/mastodon/initial_state.ts
index 324c093b4..c1cd37753 100644
--- a/app/javascript/mastodon/initial_state.ts
+++ b/app/javascript/mastodon/initial_state.ts
@@ -33,10 +33,10 @@ interface InitialStateMeta {
single_user_mode: boolean;
source_url: string;
streaming_api_base_url: string;
- local_live_feed_access: 'public' | 'authenticated';
- remote_live_feed_access: 'public' | 'authenticated';
- local_topic_feed_access: 'public' | 'authenticated';
- remote_topic_feed_access: 'public' | 'authenticated';
+ local_live_feed_access: 'public' | 'authenticated' | 'disabled';
+ remote_live_feed_access: 'public' | 'authenticated' | 'disabled';
+ local_topic_feed_access: 'public' | 'authenticated' | 'disabled';
+ remote_topic_feed_access: 'public' | 'authenticated' | 'disabled';
title: string;
show_trends: boolean;
trends_as_landing_page: boolean;
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 6917bfef3..12fb8f434 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -333,6 +333,7 @@
"empty_column.bookmarked_statuses": "You don't have any bookmarked posts yet. When you bookmark one, it will show up here.",
"empty_column.community": "The local timeline is empty. Write something publicly to get the ball rolling!",
"empty_column.direct": "You don't have any private mentions yet. When you send or receive one, it will show up here.",
+ "empty_column.disabled_feed": "This feed has been disabled by your server administrators.",
"empty_column.domain_blocks": "There are no blocked domains yet.",
"empty_column.explore_statuses": "Nothing is trending right now. Check back later!",
"empty_column.favourited_statuses": "You don't have any favorite posts yet. When you favorite one, it will show up here.",
diff --git a/app/javascript/mastodon/permissions.ts b/app/javascript/mastodon/permissions.ts
index d7695d2f5..a83e1d77a 100644
--- a/app/javascript/mastodon/permissions.ts
+++ b/app/javascript/mastodon/permissions.ts
@@ -1,3 +1,4 @@
+export const PEMRISSION_VIEW_FEEDS = 0x0000000000100000;
export const PERMISSION_INVITE_USERS = 0x0000000000010000;
export const PERMISSION_MANAGE_USERS = 0x0000000000000400;
export const PERMISSION_MANAGE_TAXONOMIES = 0x0000000000000100;
@@ -22,3 +23,19 @@ export function canManageReports(permissions: number) {
(permissions & PERMISSION_MANAGE_REPORTS) === PERMISSION_MANAGE_REPORTS
);
}
+
+export const canViewFeed = (
+ signedIn: boolean,
+ permissions: number,
+ setting: 'public' | 'authenticated' | 'disabled' | undefined,
+) => {
+ switch (setting) {
+ case 'public':
+ return true;
+ case 'authenticated':
+ return signedIn;
+ case 'disabled':
+ default:
+ return (permissions & PEMRISSION_VIEW_FEEDS) === PEMRISSION_VIEW_FEEDS;
+ }
+};