Hide disabled features (#2473)

* Hide/show on notify and fediverse feature disable/enable

* Update browser tests to enable features for testing

* Hide/show features in mobile action menu

* Do not show fediauth option if fediverse features are not enabled.

* Force showing tabs when in Storybook
This commit is contained in:
Gabe Kangas 2022-12-29 16:26:04 -08:00 committed by GitHub
parent 0eba1685b3
commit 533d33847c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 110 additions and 70 deletions

View file

@ -9,8 +9,8 @@ describe(`Basic tests`, () => {
// Offline banner
it('Has correct offline banner values', () => {
cy.contains(
'This stream is offline. Be notified the next time New Owncast Server goes live.'
).should('be.visible');
'This stream is offline. You can be notified the next time New Owncast Server goes live or follow streamer@testing.biz on the Fediverse.'
).should('exist');
});
// Verify the tags show up

View file

@ -1,4 +1,5 @@
import { setup } from '../../support/setup.js';
import fetchData from '../../support/fetchData.js';
setup();
@ -81,45 +82,3 @@ describe(`Live tests`, () => {
cy.visit('http://localhost:8080');
});
});
async function fetchData(url, options) {
const ADMIN_USERNAME = 'admin';
const ADMIN_STREAMKEY = 'abc123';
const { data, method = 'GET', auth = true } = options || {};
// eslint-disable-next-line no-undef
const requestOptions = {
method,
};
if (data) {
requestOptions.body = JSON.stringify(data);
}
if (auth && ADMIN_USERNAME && ADMIN_STREAMKEY) {
const encoded = btoa(`${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`);
requestOptions.headers = {
Authorization: `Basic ${encoded}`,
};
requestOptions.mode = 'cors';
requestOptions.credentials = 'include';
}
try {
const response = await fetch(url, requestOptions);
const json = await response.json();
if (!response.ok) {
const message =
json.message || `An error has occurred: ${response.status}`;
throw new Error(message);
}
return json;
} catch (error) {
console.error(error);
return error;
// console.log(error)
// throw new Error(error)
}
}

View file

@ -1,5 +0,0 @@
{
"name": "Using fixtures to represent data",
"email": "hello@cypress.io",
"body": "Fixtures are a great way to mock data for responses to routes"
}

View file

@ -15,6 +15,21 @@
// Import commands.js using ES2015 syntax:
import './commands';
import fetchData from './fetchData.js';
// Alternatively you can use CommonJS syntax:
// require('./commands')
// Put Owncast in a state where it's ready to be tested.
// Set server URL
fetchData('http://localhost:8080/api/admin/config/serverurl', {
method: 'POST',
data: { value: 'https://testing.biz' },
});
// Enable Fediverse features.
fetchData('http://localhost:8080/api/admin/config/federation/enable', {
method: 'POST',
data: { value: true },
});

View file

@ -0,0 +1,43 @@
async function fetchData(url, options) {
const ADMIN_USERNAME = 'admin';
const ADMIN_STREAMKEY = 'abc123';
const { data, method = 'GET', auth = true } = options || {};
// eslint-disable-next-line no-undef
const requestOptions = {
method,
};
if (data) {
requestOptions.body = JSON.stringify(data);
}
if (auth && ADMIN_USERNAME && ADMIN_STREAMKEY) {
const encoded = btoa(`${ADMIN_USERNAME}:${ADMIN_STREAMKEY}`);
requestOptions.headers = {
Authorization: `Basic ${encoded}`,
};
requestOptions.mode = 'cors';
requestOptions.credentials = 'include';
}
try {
const response = await fetch(url, requestOptions);
const json = await response.json();
if (!response.ok) {
const message =
json.message || `An error has occurred: ${response.status}`;
throw new Error(message);
}
return json;
} catch (error) {
console.error(error);
return error;
// console.log(error)
// throw new Error(error)
}
}
export default fetchData;

View file

@ -21,7 +21,7 @@ const Example = () => {
return (
<div>
<AuthModal />
<AuthModal forceTabs />
</div>
);
};

View file

@ -12,18 +12,26 @@ import {
currentUserAtom,
chatAuthenticatedAtom,
accessTokenAtom,
clientConfigStateAtom,
} from '../../stores/ClientConfigStore';
import { ClientConfig } from '../../../interfaces/client-config.model';
export const AuthModal: FC = () => {
export type AuthModalProps = {
forceTabs?: boolean;
};
export const AuthModal: FC<AuthModalProps> = ({ forceTabs }) => {
const authenticated = useRecoilValue<boolean>(chatAuthenticatedAtom);
const accessToken = useRecoilValue<string>(accessTokenAtom);
const currentUser = useRecoilValue(currentUserAtom);
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
if (!currentUser) {
return null;
}
const { displayName } = currentUser;
const federationEnabled = true;
const { federation } = clientConfig;
const { enabled: fediverseEnabled } = federation;
const indieAuthTabTitle = (
<span className={styles.tabContent}>
@ -67,7 +75,7 @@ export const AuthModal: FC = () => {
items={items}
type="card"
size="small"
renderTabBar={federationEnabled ? null : () => null}
renderTabBar={fediverseEnabled || forceTabs ? null : () => null}
/>
</div>
);

View file

@ -3,6 +3,7 @@ import { Layout, Tabs, Skeleton } from 'antd';
import { FC, useEffect, useState } from 'react';
import dynamic from 'next/dynamic';
import { LOCAL_STORAGE_KEYS, getLocalStorage, setLocalStorage } from '../../../utils/localStorage';
import isPushNotificationSupported from '../../../utils/browserPushNotifications';
import {
clientConfigStateAtom,
@ -66,16 +67,17 @@ const DesktopContent = ({
socialHandles,
extraPageContent,
setShowFollowModal,
supportFediverseFeatures,
}) => {
const aboutTabContent = <CustomPageContent content={extraPageContent} />;
const followersTabContent = (
<FollowerCollection name={name} onFollowButtonClick={() => setShowFollowModal(true)} />
);
const items = [
{ label: 'About', key: '2', children: aboutTabContent },
{ label: 'Followers', key: '3', children: followersTabContent },
];
const items = [{ label: 'About', key: '2', children: aboutTabContent }];
if (supportFediverseFeatures) {
items.push({ label: 'Followers', key: '3', children: followersTabContent });
}
return (
<>
@ -91,7 +93,7 @@ const DesktopContent = ({
</div>
<div className={styles.lowerSection}>
<Tabs defaultActiveKey="0" items={items} />
{items.length > 1 ? <Tabs defaultActiveKey="0" items={items} /> : aboutTabContent}
</div>
</>
);
@ -111,6 +113,8 @@ const MobileContent = ({
setExternalActionToDisplay,
setShowNotifyPopup,
setShowFollowModal,
supportFediverseFeatures,
supportsBrowserNotifications,
}) => {
if (!currentUser) {
return null;
@ -153,8 +157,8 @@ const MobileContent = ({
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start' }}>
<DefaultTabBar {...props} style={{ width: '85%' }} />
<ActionButtonMenu
showFollowItem
showNotifyItem
showFollowItem={supportFediverseFeatures}
showNotifyItem={supportsBrowserNotifications}
actions={actions}
externalActionSelected={setExternalActionToDisplay}
notifyItemSelected={() => setShowNotifyPopup(true)}
@ -217,11 +221,14 @@ export const Content: FC = () => {
const [showNotifyReminder, setShowNotifyReminder] = useState(false);
const [showNotifyModal, setShowNotifyModal] = useState(false);
const [showFollowModal, setShowFollowModal] = useState(false);
const { account: fediverseAccount } = federation;
const { account: fediverseAccount, enabled: fediverseEnabled } = federation;
const { browser: browserNotifications } = notifications;
const { enabled: browserNotificationsEnabled } = browserNotifications;
const [externalActionToDisplay, setExternalActionToDisplay] = useState<ExternalAction>(null);
const [supportsBrowserNotifications, setSupportsBrowserNotifications] = useState(false);
const supportFediverseFeatures = fediverseEnabled;
const externalActionSelected = (action: ExternalAction) => {
const { openExternally, url } = action;
if (openExternally) {
@ -277,6 +284,12 @@ export const Content: FC = () => {
};
}, []);
useEffect(() => {
// isPushNotificationSupported relies on `navigator` so that needs to be
// fired from this useEffect.
setSupportsBrowserNotifications(isPushNotificationSupported() && browserNotificationsEnabled);
}, [browserNotificationsEnabled]);
const showChat = !chatDisabled && isChatAvailable && isChatVisible;
return (
@ -312,14 +325,18 @@ export const Content: FC = () => {
{!isMobile && (
<ActionButtonRow>
{externalActionButtons}
<FollowButton size="small" onClick={() => setShowFollowModal(true)} />
<NotifyReminderPopup
open={showNotifyReminder}
notificationClicked={() => setShowNotifyModal(true)}
notificationClosed={() => disableNotifyReminderPopup()}
>
<NotifyButton onClick={() => setShowNotifyModal(true)} />
</NotifyReminderPopup>
{supportFediverseFeatures && (
<FollowButton size="small" onClick={() => setShowFollowModal(true)} />
)}
{supportsBrowserNotifications && (
<NotifyReminderPopup
open={showNotifyReminder}
notificationClicked={() => setShowNotifyModal(true)}
notificationClosed={() => disableNotifyReminderPopup()}
>
<NotifyButton onClick={() => setShowNotifyModal(true)} />
</NotifyReminderPopup>
)}
</ActionButtonRow>
)}
@ -348,6 +365,8 @@ export const Content: FC = () => {
setExternalActionToDisplay={externalActionSelected}
setShowNotifyPopup={setShowNotifyModal}
setShowFollowModal={setShowFollowModal}
supportFediverseFeatures={supportFediverseFeatures}
supportsBrowserNotifications={supportsBrowserNotifications}
/>
) : (
<DesktopContent
@ -358,6 +377,7 @@ export const Content: FC = () => {
socialHandles={socialHandles}
extraPageContent={extraPageContent}
setShowFollowModal={setShowFollowModal}
supportFediverseFeatures={supportFediverseFeatures}
/>
)}
<Footer version={version} />