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:
parent
0eba1685b3
commit
533d33847c
@ -9,8 +9,8 @@ describe(`Basic tests`, () => {
|
|||||||
// Offline banner
|
// Offline banner
|
||||||
it('Has correct offline banner values', () => {
|
it('Has correct offline banner values', () => {
|
||||||
cy.contains(
|
cy.contains(
|
||||||
'This stream is offline. Be notified the next time New Owncast Server goes live.'
|
'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('be.visible');
|
).should('exist');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Verify the tags show up
|
// Verify the tags show up
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { setup } from '../../support/setup.js';
|
import { setup } from '../../support/setup.js';
|
||||||
|
import fetchData from '../../support/fetchData.js';
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
@ -81,45 +82,3 @@ describe(`Live tests`, () => {
|
|||||||
cy.visit('http://localhost:8080');
|
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -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"
|
|
||||||
}
|
|
@ -15,6 +15,21 @@
|
|||||||
|
|
||||||
// Import commands.js using ES2015 syntax:
|
// Import commands.js using ES2015 syntax:
|
||||||
import './commands';
|
import './commands';
|
||||||
|
import fetchData from './fetchData.js';
|
||||||
|
|
||||||
// Alternatively you can use CommonJS syntax:
|
// Alternatively you can use CommonJS syntax:
|
||||||
// require('./commands')
|
// 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 },
|
||||||
|
});
|
||||||
|
43
test/automated/browser/cypress/support/fetchData.js
Normal file
43
test/automated/browser/cypress/support/fetchData.js
Normal 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;
|
@ -21,7 +21,7 @@ const Example = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AuthModal />
|
<AuthModal forceTabs />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -12,18 +12,26 @@ import {
|
|||||||
currentUserAtom,
|
currentUserAtom,
|
||||||
chatAuthenticatedAtom,
|
chatAuthenticatedAtom,
|
||||||
accessTokenAtom,
|
accessTokenAtom,
|
||||||
|
clientConfigStateAtom,
|
||||||
} from '../../stores/ClientConfigStore';
|
} 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 authenticated = useRecoilValue<boolean>(chatAuthenticatedAtom);
|
||||||
const accessToken = useRecoilValue<string>(accessTokenAtom);
|
const accessToken = useRecoilValue<string>(accessTokenAtom);
|
||||||
const currentUser = useRecoilValue(currentUserAtom);
|
const currentUser = useRecoilValue(currentUserAtom);
|
||||||
|
const clientConfig = useRecoilValue<ClientConfig>(clientConfigStateAtom);
|
||||||
|
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const { displayName } = currentUser;
|
const { displayName } = currentUser;
|
||||||
|
const { federation } = clientConfig;
|
||||||
const federationEnabled = true;
|
const { enabled: fediverseEnabled } = federation;
|
||||||
|
|
||||||
const indieAuthTabTitle = (
|
const indieAuthTabTitle = (
|
||||||
<span className={styles.tabContent}>
|
<span className={styles.tabContent}>
|
||||||
@ -67,7 +75,7 @@ export const AuthModal: FC = () => {
|
|||||||
items={items}
|
items={items}
|
||||||
type="card"
|
type="card"
|
||||||
size="small"
|
size="small"
|
||||||
renderTabBar={federationEnabled ? null : () => null}
|
renderTabBar={fediverseEnabled || forceTabs ? null : () => null}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -3,6 +3,7 @@ import { Layout, Tabs, Skeleton } from 'antd';
|
|||||||
import { FC, useEffect, useState } from 'react';
|
import { FC, useEffect, useState } from 'react';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
import { LOCAL_STORAGE_KEYS, getLocalStorage, setLocalStorage } from '../../../utils/localStorage';
|
import { LOCAL_STORAGE_KEYS, getLocalStorage, setLocalStorage } from '../../../utils/localStorage';
|
||||||
|
import isPushNotificationSupported from '../../../utils/browserPushNotifications';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
clientConfigStateAtom,
|
clientConfigStateAtom,
|
||||||
@ -66,16 +67,17 @@ const DesktopContent = ({
|
|||||||
socialHandles,
|
socialHandles,
|
||||||
extraPageContent,
|
extraPageContent,
|
||||||
setShowFollowModal,
|
setShowFollowModal,
|
||||||
|
supportFediverseFeatures,
|
||||||
}) => {
|
}) => {
|
||||||
const aboutTabContent = <CustomPageContent content={extraPageContent} />;
|
const aboutTabContent = <CustomPageContent content={extraPageContent} />;
|
||||||
const followersTabContent = (
|
const followersTabContent = (
|
||||||
<FollowerCollection name={name} onFollowButtonClick={() => setShowFollowModal(true)} />
|
<FollowerCollection name={name} onFollowButtonClick={() => setShowFollowModal(true)} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const items = [
|
const items = [{ label: 'About', key: '2', children: aboutTabContent }];
|
||||||
{ label: 'About', key: '2', children: aboutTabContent },
|
if (supportFediverseFeatures) {
|
||||||
{ label: 'Followers', key: '3', children: followersTabContent },
|
items.push({ label: 'Followers', key: '3', children: followersTabContent });
|
||||||
];
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -91,7 +93,7 @@ const DesktopContent = ({
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.lowerSection}>
|
<div className={styles.lowerSection}>
|
||||||
<Tabs defaultActiveKey="0" items={items} />
|
{items.length > 1 ? <Tabs defaultActiveKey="0" items={items} /> : aboutTabContent}
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
@ -111,6 +113,8 @@ const MobileContent = ({
|
|||||||
setExternalActionToDisplay,
|
setExternalActionToDisplay,
|
||||||
setShowNotifyPopup,
|
setShowNotifyPopup,
|
||||||
setShowFollowModal,
|
setShowFollowModal,
|
||||||
|
supportFediverseFeatures,
|
||||||
|
supportsBrowserNotifications,
|
||||||
}) => {
|
}) => {
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
return null;
|
return null;
|
||||||
@ -153,8 +157,8 @@ const MobileContent = ({
|
|||||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start' }}>
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'start' }}>
|
||||||
<DefaultTabBar {...props} style={{ width: '85%' }} />
|
<DefaultTabBar {...props} style={{ width: '85%' }} />
|
||||||
<ActionButtonMenu
|
<ActionButtonMenu
|
||||||
showFollowItem
|
showFollowItem={supportFediverseFeatures}
|
||||||
showNotifyItem
|
showNotifyItem={supportsBrowserNotifications}
|
||||||
actions={actions}
|
actions={actions}
|
||||||
externalActionSelected={setExternalActionToDisplay}
|
externalActionSelected={setExternalActionToDisplay}
|
||||||
notifyItemSelected={() => setShowNotifyPopup(true)}
|
notifyItemSelected={() => setShowNotifyPopup(true)}
|
||||||
@ -217,11 +221,14 @@ export const Content: FC = () => {
|
|||||||
const [showNotifyReminder, setShowNotifyReminder] = useState(false);
|
const [showNotifyReminder, setShowNotifyReminder] = useState(false);
|
||||||
const [showNotifyModal, setShowNotifyModal] = useState(false);
|
const [showNotifyModal, setShowNotifyModal] = useState(false);
|
||||||
const [showFollowModal, setShowFollowModal] = useState(false);
|
const [showFollowModal, setShowFollowModal] = useState(false);
|
||||||
const { account: fediverseAccount } = federation;
|
const { account: fediverseAccount, enabled: fediverseEnabled } = federation;
|
||||||
const { browser: browserNotifications } = notifications;
|
const { browser: browserNotifications } = notifications;
|
||||||
const { enabled: browserNotificationsEnabled } = browserNotifications;
|
const { enabled: browserNotificationsEnabled } = browserNotifications;
|
||||||
const [externalActionToDisplay, setExternalActionToDisplay] = useState<ExternalAction>(null);
|
const [externalActionToDisplay, setExternalActionToDisplay] = useState<ExternalAction>(null);
|
||||||
|
|
||||||
|
const [supportsBrowserNotifications, setSupportsBrowserNotifications] = useState(false);
|
||||||
|
const supportFediverseFeatures = fediverseEnabled;
|
||||||
|
|
||||||
const externalActionSelected = (action: ExternalAction) => {
|
const externalActionSelected = (action: ExternalAction) => {
|
||||||
const { openExternally, url } = action;
|
const { openExternally, url } = action;
|
||||||
if (openExternally) {
|
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;
|
const showChat = !chatDisabled && isChatAvailable && isChatVisible;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -312,7 +325,10 @@ export const Content: FC = () => {
|
|||||||
{!isMobile && (
|
{!isMobile && (
|
||||||
<ActionButtonRow>
|
<ActionButtonRow>
|
||||||
{externalActionButtons}
|
{externalActionButtons}
|
||||||
|
{supportFediverseFeatures && (
|
||||||
<FollowButton size="small" onClick={() => setShowFollowModal(true)} />
|
<FollowButton size="small" onClick={() => setShowFollowModal(true)} />
|
||||||
|
)}
|
||||||
|
{supportsBrowserNotifications && (
|
||||||
<NotifyReminderPopup
|
<NotifyReminderPopup
|
||||||
open={showNotifyReminder}
|
open={showNotifyReminder}
|
||||||
notificationClicked={() => setShowNotifyModal(true)}
|
notificationClicked={() => setShowNotifyModal(true)}
|
||||||
@ -320,6 +336,7 @@ export const Content: FC = () => {
|
|||||||
>
|
>
|
||||||
<NotifyButton onClick={() => setShowNotifyModal(true)} />
|
<NotifyButton onClick={() => setShowNotifyModal(true)} />
|
||||||
</NotifyReminderPopup>
|
</NotifyReminderPopup>
|
||||||
|
)}
|
||||||
</ActionButtonRow>
|
</ActionButtonRow>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -348,6 +365,8 @@ export const Content: FC = () => {
|
|||||||
setExternalActionToDisplay={externalActionSelected}
|
setExternalActionToDisplay={externalActionSelected}
|
||||||
setShowNotifyPopup={setShowNotifyModal}
|
setShowNotifyPopup={setShowNotifyModal}
|
||||||
setShowFollowModal={setShowFollowModal}
|
setShowFollowModal={setShowFollowModal}
|
||||||
|
supportFediverseFeatures={supportFediverseFeatures}
|
||||||
|
supportsBrowserNotifications={supportsBrowserNotifications}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<DesktopContent
|
<DesktopContent
|
||||||
@ -358,6 +377,7 @@ export const Content: FC = () => {
|
|||||||
socialHandles={socialHandles}
|
socialHandles={socialHandles}
|
||||||
extraPageContent={extraPageContent}
|
extraPageContent={extraPageContent}
|
||||||
setShowFollowModal={setShowFollowModal}
|
setShowFollowModal={setShowFollowModal}
|
||||||
|
supportFediverseFeatures={supportFediverseFeatures}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Footer version={version} />
|
<Footer version={version} />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user