Browse Source
* chore(js): be stricter about dead code warnings * chore(js): remove dead code and unused exports * rebase * chore: remove unused files * chore(deps): remove unused prop-types dep * chore(js): remove unused function * chore(deps): remove + check unused deps * chore(js): remove unused exports. Closes #3036pull/3039/head
55 changed files with 1187 additions and 1071 deletions
@ -0,0 +1,72 @@ |
|||||||
|
{ |
||||||
|
"ignore": [ |
||||||
|
"**/.eslintrc.js", |
||||||
|
".storybook/**", |
||||||
|
"**/*config.?s", |
||||||
|
"**/*mock.?s", |
||||||
|
"**/*fixture.?s", |
||||||
|
"next-env.d.ts", |
||||||
|
"public/**" |
||||||
|
], |
||||||
|
"ignoreDependencies": [ |
||||||
|
"@fontsource/inter", |
||||||
|
"@fontsource/poppins", |
||||||
|
"@next/bundle-analyzer", |
||||||
|
"autoprefixer", |
||||||
|
"webpack-deadcode-plugin", |
||||||
|
"yaml", |
||||||
|
"postcss-flexbugs-fixes", |
||||||
|
"sharp", |
||||||
|
"next-with-less", |
||||||
|
"next-pwa", |
||||||
|
"workbox-precaching", |
||||||
|
"workbox-window", |
||||||
|
"@storybook/addon-a11y", |
||||||
|
"@storybook/addon-docs", |
||||||
|
"@storybook/addon-essentials", |
||||||
|
"@storybook/addon-links", |
||||||
|
"@storybook/addon-postcss", |
||||||
|
"@storybook/addon-viewport", |
||||||
|
"@storybook/builder-webpack5", |
||||||
|
"@storybook/cli", |
||||||
|
"@storybook/manager-webpack5", |
||||||
|
"@storybook/mdx2-csf", |
||||||
|
"@storybook/preset-scss", |
||||||
|
"@mdx-js/react", |
||||||
|
"@storybook/testing-library", |
||||||
|
"@svgr/webpack", |
||||||
|
"@types/jest", |
||||||
|
"@types/markdown-it", |
||||||
|
"@types/prop-types", |
||||||
|
"@typescript-eslint/eslint-plugin", |
||||||
|
"@typescript-eslint/parser", |
||||||
|
"babel-loader", |
||||||
|
"chromatic", |
||||||
|
"css-loader", |
||||||
|
"cypress", |
||||||
|
"eslint-config-airbnb", |
||||||
|
"eslint-config-next", |
||||||
|
"eslint-config-prettier", |
||||||
|
"eslint-plugin-import", |
||||||
|
"eslint-plugin-jsx-a11y", |
||||||
|
"eslint-plugin-prettier", |
||||||
|
"eslint-plugin-react", |
||||||
|
"eslint-plugin-react-hooks", |
||||||
|
"eslint-plugin-storybook", |
||||||
|
"handlebars", |
||||||
|
"html-webpack-plugin", |
||||||
|
"install", |
||||||
|
"less", |
||||||
|
"less-loader", |
||||||
|
"mdx-mermaid", |
||||||
|
"mermaid", |
||||||
|
"prettier", |
||||||
|
"sass-loader", |
||||||
|
"sb", |
||||||
|
"storybook-addon-designs", |
||||||
|
"storybook-addon-fetch-mock", |
||||||
|
"storybook-preset-less", |
||||||
|
"style-loader", |
||||||
|
"ts-jest" |
||||||
|
] |
||||||
|
} |
||||||
@ -1,71 +0,0 @@ |
|||||||
// Note: references to "yp" in the app are likely related to Owncast Directory
|
|
||||||
import React, { useState, useContext, useEffect, FC } from 'react'; |
|
||||||
import { Typography } from 'antd'; |
|
||||||
|
|
||||||
import { ToggleSwitch } from './ToggleSwitch'; |
|
||||||
import { ServerStatusContext } from '../../utils/server-status-context'; |
|
||||||
import { FIELD_PROPS_NSFW, FIELD_PROPS_YP } from '../../utils/config-constants'; |
|
||||||
|
|
||||||
const { Title } = Typography; |
|
||||||
|
|
||||||
// eslint-disable-next-line import/prefer-default-export
|
|
||||||
export const EditYPDetails: FC = () => { |
|
||||||
const [formDataValues, setFormDataValues] = useState(null); |
|
||||||
|
|
||||||
const serverStatusData = useContext(ServerStatusContext); |
|
||||||
const { serverConfig } = serverStatusData || {}; |
|
||||||
|
|
||||||
const { yp, instanceDetails } = serverConfig; |
|
||||||
const { nsfw } = instanceDetails; |
|
||||||
const { enabled, instanceUrl } = yp; |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
setFormDataValues({ |
|
||||||
...yp, |
|
||||||
enabled, |
|
||||||
nsfw, |
|
||||||
}); |
|
||||||
}, [yp, instanceDetails]); |
|
||||||
|
|
||||||
const hasInstanceUrl = instanceUrl !== ''; |
|
||||||
if (!formDataValues) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
return ( |
|
||||||
<div className="config-directory-details-form"> |
|
||||||
<Title level={3} className="section-title"> |
|
||||||
Owncast Directory Settings |
|
||||||
</Title> |
|
||||||
|
|
||||||
<p className="description"> |
|
||||||
Would you like to appear in the{' '} |
|
||||||
<a href="https://directory.owncast.online" target="_blank" rel="noreferrer"> |
|
||||||
<strong>Owncast Directory</strong> |
|
||||||
</a> |
|
||||||
? |
|
||||||
</p> |
|
||||||
|
|
||||||
<p style={{ backgroundColor: 'black', fontSize: '.75rem', padding: '5px' }}> |
|
||||||
<em> |
|
||||||
NOTE: You will need to have a URL specified in the <code>Instance URL</code> field to be |
|
||||||
able to use this. |
|
||||||
</em> |
|
||||||
</p> |
|
||||||
|
|
||||||
<div className="config-yp-container"> |
|
||||||
<ToggleSwitch |
|
||||||
fieldName="enabled" |
|
||||||
{...FIELD_PROPS_YP} |
|
||||||
checked={formDataValues.enabled} |
|
||||||
disabled={!hasInstanceUrl} |
|
||||||
/> |
|
||||||
<ToggleSwitch |
|
||||||
fieldName="nsfw" |
|
||||||
{...FIELD_PROPS_NSFW} |
|
||||||
checked={formDataValues.nsfw} |
|
||||||
disabled={!hasInstanceUrl} |
|
||||||
/> |
|
||||||
</div> |
|
||||||
</div> |
|
||||||
); |
|
||||||
}; |
|
||||||
@ -1,27 +0,0 @@ |
|||||||
import { Tooltip } from 'antd'; |
|
||||||
import dynamic from 'next/dynamic'; |
|
||||||
import { FC } from 'react'; |
|
||||||
|
|
||||||
// Lazy loaded components
|
|
||||||
|
|
||||||
const InfoCircleOutlined = dynamic(() => import('@ant-design/icons/InfoCircleOutlined'), { |
|
||||||
ssr: false, |
|
||||||
}); |
|
||||||
|
|
||||||
export type InfoTipProps = { |
|
||||||
tip: string | null; |
|
||||||
}; |
|
||||||
|
|
||||||
export const InfoTip: FC<InfoTipProps> = ({ tip }) => { |
|
||||||
if (tip === '' || tip === null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
return ( |
|
||||||
<span className="info-tip"> |
|
||||||
<Tooltip title={tip}> |
|
||||||
<InfoCircleOutlined /> |
|
||||||
</Tooltip> |
|
||||||
</span> |
|
||||||
); |
|
||||||
}; |
|
||||||
@ -1,31 +0,0 @@ |
|||||||
import { Table, Typography } from 'antd'; |
|
||||||
import { FC } from 'react'; |
|
||||||
|
|
||||||
const { Title } = Typography; |
|
||||||
|
|
||||||
export type KeyValueTableProps = { |
|
||||||
title: string; |
|
||||||
data: any; |
|
||||||
}; |
|
||||||
|
|
||||||
export const KeyValueTable: FC<KeyValueTableProps> = ({ title, data }) => { |
|
||||||
const columns = [ |
|
||||||
{ |
|
||||||
title: 'Name', |
|
||||||
dataIndex: 'name', |
|
||||||
key: 'name', |
|
||||||
}, |
|
||||||
{ |
|
||||||
title: 'Value', |
|
||||||
dataIndex: 'value', |
|
||||||
key: 'value', |
|
||||||
}, |
|
||||||
]; |
|
||||||
|
|
||||||
return ( |
|
||||||
<> |
|
||||||
<Title level={2}>{title}</Title> |
|
||||||
<Table pagination={false} columns={columns} dataSource={data} rowKey="name" /> |
|
||||||
</> |
|
||||||
); |
|
||||||
}; |
|
||||||
@ -1,29 +0,0 @@ |
|||||||
import { CSSProperties, FC } from 'react'; |
|
||||||
|
|
||||||
export type ModIconProps = { |
|
||||||
style?: CSSProperties; |
|
||||||
fill?: string; |
|
||||||
stroke?: string; |
|
||||||
}; |
|
||||||
|
|
||||||
export const ModIcon: FC<ModIconProps> = ({ |
|
||||||
style = { width: '1rem', height: '1rem' }, |
|
||||||
fill = 'none', |
|
||||||
stroke = 'var(--color-owncast-gray-300)', |
|
||||||
}: ModIconProps) => ( |
|
||||||
<svg |
|
||||||
fill={fill} |
|
||||||
stroke={stroke} |
|
||||||
style={style} |
|
||||||
viewBox="0 0 24 24" |
|
||||||
xmlns="http://www.w3.org/2000/svg" |
|
||||||
> |
|
||||||
<title>This user has moderation rights</title> |
|
||||||
<path |
|
||||||
strokeLinecap="round" |
|
||||||
strokeLinejoin="round" |
|
||||||
strokeWidth={2} |
|
||||||
d="M9 12l2 2 4-4m5.618-4.016A11.955 11.955 0 0112 2.944a11.955 11.955 0 01-8.618 3.04A12.02 12.02 0 003 9c0 5.591 3.824 10.29 9 11.622 5.176-1.332 9-6.03 9-11.622 0-1.042-.133-2.052-.382-3.016z" |
|
||||||
/> |
|
||||||
</svg> |
|
||||||
); |
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,78 +1 @@ |
|||||||
// misc constants used throughout the app
|
|
||||||
|
|
||||||
export const URL_STATUS = `/api/status`; |
|
||||||
export const URL_CHAT_HISTORY = `/api/chat`; |
|
||||||
export const URL_CUSTOM_EMOJIS = `/api/emoji`; |
|
||||||
export const URL_CONFIG = `/api/config`; |
|
||||||
export const URL_VIEWER_PING = `/api/ping`; |
|
||||||
|
|
||||||
// inline moderation actions
|
|
||||||
export const URL_HIDE_MESSAGE = `/api/chat/messagevisibility`; |
|
||||||
export const URL_BAN_USER = `/api/chat/users/setenabled`; |
|
||||||
|
|
||||||
// TODO: This directory is customizable in the config. So we should expose this via the config API.
|
|
||||||
export const URL_STREAM = `/hls/stream.m3u8`; |
|
||||||
// export const URL_WEBSOCKET = `${location.protocol === 'https:' ? 'wss' : 'ws'}://${
|
|
||||||
// location.host
|
|
||||||
// }/ws`;
|
|
||||||
export const URL_CHAT_REGISTRATION = `/api/chat/register`; |
|
||||||
export const URL_FOLLOWERS = `/api/followers`; |
|
||||||
export const URL_PLAYBACK_METRICS = `/api/metrics/playback`; |
|
||||||
|
|
||||||
export const URL_REGISTER_NOTIFICATION = `/api/notifications/register`; |
|
||||||
export const URL_REGISTER_EMAIL_NOTIFICATION = `/api/notifications/register/email`; |
|
||||||
export const URL_CHAT_INDIEAUTH_BEGIN = `/api/auth/indieauth`; |
|
||||||
|
|
||||||
export const TIMER_STATUS_UPDATE = 5000; // ms
|
|
||||||
export const TIMER_DISABLE_CHAT_AFTER_OFFLINE = 5 * 60 * 1000; // 5 mins
|
|
||||||
export const TIMER_STREAM_DURATION_COUNTER = 1000; |
|
||||||
export const TEMP_IMAGE = |
|
||||||
'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'; |
|
||||||
|
|
||||||
export const OWNCAST_LOGO_LOCAL = '/img/logo.svg'; |
|
||||||
|
|
||||||
export const MESSAGE_OFFLINE = 'Stream is offline.'; |
|
||||||
export const MESSAGE_ONLINE = 'Stream is online.'; |
|
||||||
|
|
||||||
export const URL_OWNCAST = 'https://owncast.online'; // used in footer
|
|
||||||
export const PLAYER_VOLUME = 'owncast_volume'; |
|
||||||
|
|
||||||
export const KEY_ACCESS_TOKEN = 'owncast_access_token'; |
|
||||||
export const KEY_EMBED_CHAT_ACCESS_TOKEN = 'owncast_embed_chat_access_token'; |
|
||||||
export const KEY_USERNAME = 'owncast_username'; |
|
||||||
export const KEY_CUSTOM_USERNAME_SET = 'owncast_custom_username_set'; |
|
||||||
export const KEY_CHAT_DISPLAYED = 'owncast_chat'; |
|
||||||
export const KEY_CHAT_FIRST_MESSAGE_SENT = 'owncast_first_message_sent'; |
|
||||||
export const CHAT_INITIAL_PLACEHOLDER_TEXT = 'Type here to chat, no account necessary.'; |
|
||||||
export const CHAT_PLACEHOLDER_TEXT = 'Message'; |
|
||||||
export const CHAT_PLACEHOLDER_OFFLINE = 'Chat is offline.'; |
|
||||||
export const CHAT_MAX_MESSAGE_LENGTH = 500; |
|
||||||
export const EST_SOCKET_PAYLOAD_BUFFER = 512; |
|
||||||
export const CHAT_CHAR_COUNT_BUFFER = 20; |
|
||||||
export const CHAT_OK_KEYCODES = [ |
|
||||||
'ArrowLeft', |
|
||||||
'ArrowUp', |
|
||||||
'ArrowRight', |
|
||||||
'ArrowDown', |
|
||||||
'Shift', |
|
||||||
'Meta', |
|
||||||
'Alt', |
|
||||||
'Delete', |
|
||||||
'Backspace', |
|
||||||
]; |
|
||||||
export const CHAT_KEY_MODIFIERS = ['Control', 'Shift', 'Meta', 'Alt']; |
|
||||||
export const MESSAGE_JUMPTOBOTTOM_BUFFER = 500; |
|
||||||
|
|
||||||
// app styling
|
|
||||||
export const WIDTH_SINGLE_COL = 780; |
|
||||||
export const HEIGHT_SHORT_WIDE = 500; |
|
||||||
export const ORIENTATION_PORTRAIT = 'portrait'; |
|
||||||
export const ORIENTATION_LANDSCAPE = 'landscape'; |
|
||||||
|
|
||||||
// localstorage keys
|
|
||||||
export const HAS_DISPLAYED_NOTIFICATION_MODAL_KEY = 'HAS_DISPLAYED_NOTIFICATION_MODAL'; |
|
||||||
export const USER_VISIT_COUNT_KEY = 'USER_VISIT_COUNT'; |
|
||||||
export const USER_DISMISSED_ANNOYING_NOTIFICATION_POPUP_KEY = |
|
||||||
'USER_DISMISSED_ANNOYING_NOTIFICATION_POPUP_KEY'; |
|
||||||
|
|
||||||
export const DYNAMIC_PADDING_VALUE = '320px'; |
export const DYNAMIC_PADDING_VALUE = '320px'; |
||||||
|
|||||||
@ -1,32 +0,0 @@ |
|||||||
import { useState, useEffect } from 'react'; |
|
||||||
|
|
||||||
export default function useWindowSize() { |
|
||||||
// Initialize state with undefined width/height so server and client renders match
|
|
||||||
// Learn more here: https://joshwcomeau.com/react/the-perils-of-rehydration/
|
|
||||||
const [windowSize, setWindowSize] = useState({ |
|
||||||
width: undefined, |
|
||||||
height: undefined, |
|
||||||
}); |
|
||||||
|
|
||||||
useEffect(() => { |
|
||||||
// Handler to call on window resize
|
|
||||||
function handleResize() { |
|
||||||
// Set window width/height to state
|
|
||||||
setWindowSize({ |
|
||||||
width: window.innerWidth, |
|
||||||
height: window.innerHeight, |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
// Add event listener
|
|
||||||
window.addEventListener('resize', handleResize); |
|
||||||
|
|
||||||
// Call handler right away so state gets updated with initial window size
|
|
||||||
handleResize(); |
|
||||||
|
|
||||||
// Remove event listener on cleanup
|
|
||||||
return () => window.removeEventListener('resize', handleResize); |
|
||||||
}, []); // Empty array ensures that effect is only run on mount
|
|
||||||
|
|
||||||
return windowSize; |
|
||||||
} |
|
||||||
Loading…
Reference in new issue