Developers: add Service Worker debug page

This commit is contained in:
Alex Gleason
2022-11-03 18:48:10 -05:00
parent 3d25dc7f3c
commit 66cd92970b
9 changed files with 199 additions and 15 deletions

View File

@ -0,0 +1,24 @@
import classNames from 'clsx';
import React from 'react';
interface IIndicator {
state?: 'active' | 'pending' | 'error' | 'inactive',
size?: 'sm',
}
/** Indicator dot component. */
const Indicator: React.FC<IIndicator> = ({ state = 'inactive', size = 'sm' }) => {
return (
<div
className={classNames('rounded-full outline-double', {
'w-1.5 h-1.5 shadow-sm': size === 'sm',
'bg-green-500 outline-green-400': state === 'active',
'bg-yellow-500 outline-yellow-400': state === 'pending',
'bg-red-500 outline-red-400': state === 'error',
'bg-neutral-500 outline-neutral-400': state === 'inactive',
})}
/>
);
};
export default Indicator;

View File

@ -89,6 +89,14 @@ const Developers: React.FC = () => {
</Text>
</DashWidget>
<DashWidget to='/developers/sw'>
<SvgIcon src={require('@tabler/icons/script.svg')} className='text-gray-700 dark:text-gray-600' />
<Text>
<FormattedMessage id='developers.navigation.service_worker_label' defaultMessage='Service Worker' />
</Text>
</DashWidget>
<DashWidget onClick={leaveDevelopers}>
<SvgIcon src={require('@tabler/icons/logout.svg')} className='text-gray-700 dark:text-gray-600' />

View File

@ -0,0 +1,140 @@
import React, { useEffect, useState } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import List, { ListItem } from 'soapbox/components/list';
import { HStack, Text, Column, FormActions, Button, Stack, Icon } from 'soapbox/components/ui';
import { unregisterSw } from 'soapbox/utils/sw';
import Indicator from './components/indicator';
const messages = defineMessages({
heading: { id: 'column.developers.service_worker', defaultMessage: 'Service Worker' },
status: { id: 'sw.status', defaultMessage: 'Status' },
url: { id: 'sw.url', defaultMessage: 'Script URL' },
});
/** Hook that returns the active ServiceWorker registration. */
const useRegistration = () => {
const [isLoading, setLoading] = useState(true);
const [registration, setRegistration] = useState<ServiceWorkerRegistration>();
const isSupported = 'serviceWorker' in navigator;
useEffect(() => {
if (isSupported) {
navigator.serviceWorker.getRegistration()
.then(r => {
setRegistration(r);
setLoading(false);
})
.catch(() => setLoading(false));
} else {
setLoading(false);
}
}, []);
return {
isLoading,
registration,
};
};
interface IServiceWorkerInfo {
}
/** Mini ServiceWorker debugging component. */
const ServiceWorkerInfo: React.FC<IServiceWorkerInfo> = () => {
const intl = useIntl();
const { isLoading, registration } = useRegistration();
const url = registration?.active?.scriptURL;
const getState = () => {
if (registration?.active) {
return 'active';
} else if (registration?.waiting) {
return 'pending';
} else {
return 'inactive';
}
};
const getMessage = () => {
if (isLoading) {
return (
<FormattedMessage
id='sw.state.loading'
defaultMessage='Loading…'
/>
);
} else if (!isLoading && !registration) {
return (
<FormattedMessage
id='sw.state.unavailable'
defaultMessage='Unavailable'
/>
);
} else if (registration?.active) {
return (
<FormattedMessage
id='sw.state.active'
defaultMessage='Active'
/>
);
} else if (registration?.waiting) {
return (
<FormattedMessage
id='sw.state.waiting'
defaultMessage='Waiting'
/>
);
} else {
return (
<FormattedMessage
id='sw.state.unknown'
defaultMessage='Unknown'
/>
);
}
};
const handleRestart = async() => {
await unregisterSw();
window.location.reload();
};
return (
<Column label={intl.formatMessage(messages.heading)} backHref='/developers'>
<Stack space={4}>
<List>
<ListItem label={intl.formatMessage(messages.status)}>
<HStack alignItems='center' space={2}>
<Indicator state={getState()} />
<Text size='md' theme='muted'>{getMessage()}</Text>
</HStack>
</ListItem>
{url && (
<ListItem label={intl.formatMessage(messages.url)}>
<a href={url} target='_blank' className='flex space-x-1 items-center truncate'>
<span className='truncate'>{url}</span>
<Icon
className='w-4 h-4'
src={require('@tabler/icons/external-link.svg')}
/>
</a>
</ListItem>
)}
</List>
<FormActions>
<Button theme='tertiary' type='button' onClick={handleRestart}>
<FormattedMessage id='sw.restart' defaultMessage='Restart' />
</Button>
</FormActions>
</Stack>
</Column>
);
};
export default ServiceWorkerInfo;