diff --git a/app/fonts/OpenDyslexic/OFL.txt b/app/fonts/OpenDyslexic/LICENSE
similarity index 100%
rename from app/fonts/OpenDyslexic/OFL.txt
rename to app/fonts/OpenDyslexic/LICENSE
diff --git a/app/soapbox/features/compose/components/navigation_bar.js b/app/soapbox/features/compose/components/navigation_bar.js
deleted file mode 100644
index 435bd5ee9..000000000
--- a/app/soapbox/features/compose/components/navigation_bar.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import ImmutablePropTypes from 'react-immutable-proptypes';
-import ActionBar from './action_bar';
-import Avatar from '../../../components/avatar';
-import Permalink from '../../../components/permalink';
-import IconButton from '../../../components/icon_button';
-import { FormattedMessage } from 'react-intl';
-import ImmutablePureComponent from 'react-immutable-pure-component';
-
-export default class NavigationBar extends ImmutablePureComponent {
-
- static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
- onClose: PropTypes.func,
- };
-
- render() {
- return (
-
-
- {this.props.account.get('acct')}
-
-
-
-
-
- @{this.props.account.get('acct')}
-
-
-
-
-
-
-
- );
- }
-
-}
diff --git a/app/soapbox/features/compose/containers/navigation_container.js b/app/soapbox/features/compose/containers/navigation_container.js
deleted file mode 100644
index 31a9b4285..000000000
--- a/app/soapbox/features/compose/containers/navigation_container.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { connect } from 'react-redux';
-import NavigationBar from '../components/navigation_bar';
-
-const mapStateToProps = state => {
- const me = state.get('me');
- return {
- account: state.getIn(['accounts', me]),
- };
-};
-
-export default connect(mapStateToProps)(NavigationBar);
diff --git a/app/soapbox/features/compose/index.js b/app/soapbox/features/compose/index.js
deleted file mode 100644
index c66c5b82a..000000000
--- a/app/soapbox/features/compose/index.js
+++ /dev/null
@@ -1,123 +0,0 @@
-import React from 'react';
-import ComposeFormContainer from './containers/compose_form_container';
-import NavigationContainer from './containers/navigation_container';
-import PropTypes from 'prop-types';
-import ImmutablePropTypes from 'react-immutable-proptypes';
-import { connect } from 'react-redux';
-import { mountCompose, unmountCompose } from '../../actions/compose';
-import { Link } from 'react-router-dom';
-import { injectIntl, defineMessages } from 'react-intl';
-import SearchContainer from './containers/search_container';
-import Motion from '../ui/util/optional_motion';
-import spring from 'react-motion/lib/spring';
-import SearchResultsContainer from './containers/search_results_container';
-import { changeComposing } from '../../actions/compose';
-import Icon from 'soapbox/components/icon';
-import { getSettings } from 'soapbox/actions/settings';
-
-const messages = defineMessages({
- start: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
- home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' },
- notifications: { id: 'tabs_bar.notifications', defaultMessage: 'Notifications' },
- public: { id: 'navigation_bar.public_timeline', defaultMessage: 'Federated timeline' },
- community: { id: 'navigation_bar.community_timeline', defaultMessage: 'Local timeline' },
- preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
- logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
- compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new post' },
-});
-
-const mapStateToProps = (state, ownProps) => ({
- columns: getSettings(state).get('columns'),
- showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : ownProps.isSearchPage,
-});
-
-export default @connect(mapStateToProps)
-@injectIntl
-class Compose extends React.PureComponent {
-
- static propTypes = {
- dispatch: PropTypes.func.isRequired,
- columns: ImmutablePropTypes.list.isRequired,
- multiColumn: PropTypes.bool,
- showSearch: PropTypes.bool,
- isSearchPage: PropTypes.bool,
- intl: PropTypes.object.isRequired,
- };
-
- componentDidMount() {
- const { isSearchPage } = this.props;
-
- if (!isSearchPage) {
- this.props.dispatch(mountCompose());
- }
- }
-
- componentWillUnmount() {
- const { isSearchPage } = this.props;
-
- if (!isSearchPage) {
- this.props.dispatch(unmountCompose());
- }
- }
-
- onFocus = () => {
- this.props.dispatch(changeComposing(true));
- }
-
- onBlur = () => {
- this.props.dispatch(changeComposing(false));
- }
-
- render() {
- const { multiColumn, showSearch, isSearchPage, intl } = this.props;
-
- let header = '';
-
- if (multiColumn) {
- const { columns } = this.props;
- header = (
-
- );
- }
-
- return (
-
- {header}
-
- {(multiColumn || isSearchPage) &&
}
-
-
- {!isSearchPage &&
-
-
-
}
-
-
- {({ x }) => (
-
-
-
- )}
-
-
-
- );
- }
-
-}
diff --git a/app/soapbox/features/getting_started/index.js b/app/soapbox/features/getting_started/index.js
deleted file mode 100644
index 34b1cbc65..000000000
--- a/app/soapbox/features/getting_started/index.js
+++ /dev/null
@@ -1,158 +0,0 @@
-import React from 'react';
-import Column from '../ui/components/column';
-import ColumnLink from '../ui/components/column_link';
-import ColumnSubheading from '../ui/components/column_subheading';
-import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
-import { connect } from 'react-redux';
-import PropTypes from 'prop-types';
-import ImmutablePropTypes from 'react-immutable-proptypes';
-import ImmutablePureComponent from 'react-immutable-pure-component';
-import { fetchFollowRequests } from 'soapbox/actions/accounts';
-import { List as ImmutableList } from 'immutable';
-import NavigationBar from '../compose/components/navigation_bar';
-import Icon from 'soapbox/components/icon';
-import LinkFooter from 'soapbox/features/ui/components/link_footer';
-
-const messages = defineMessages({
- home_timeline: { id: 'tabs_bar.home', defaultMessage: 'Home' },
- notifications: { id: 'tabs_bar.notifications', defaultMessage: 'Notifications' },
- settings_subheading: { id: 'column_subheading.settings', defaultMessage: 'Settings' },
- direct: { id: 'navigation_bar.direct', defaultMessage: 'Direct messages' },
- preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
- follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
- favourites: { id: 'navigation_bar.favourites', defaultMessage: 'Likes' },
- blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
- domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
- mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
- pins: { id: 'navigation_bar.pins', defaultMessage: 'Pinned posts' },
- lists: { id: 'navigation_bar.lists', defaultMessage: 'Lists' },
- discover: { id: 'navigation_bar.discover', defaultMessage: 'Discover' },
- personal: { id: 'navigation_bar.personal', defaultMessage: 'Personal' },
- security: { id: 'navigation_bar.security', defaultMessage: 'Security' },
- menu: { id: 'getting_started.heading', defaultMessage: 'Getting started' },
-});
-
-const mapStateToProps = state => {
- const me = state.get('me');
- return {
- myAccount: state.getIn(['accounts', me]),
- unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
- };
-};
-
-const mapDispatchToProps = dispatch => ({
- fetchFollowRequests: () => dispatch(fetchFollowRequests()),
-});
-
-const badgeDisplay = (number, limit) => {
- if (number === 0) {
- return undefined;
- } else if (limit && number >= limit) {
- return `${limit}+`;
- } else {
- return number;
- }
-};
-
-const NAVIGATION_PANEL_BREAKPOINT = 600 + (285 * 2) + (10 * 2);
-
-export default @connect(mapStateToProps, mapDispatchToProps)
-@injectIntl
-class GettingStarted extends ImmutablePureComponent {
-
- static contextTypes = {
- router: PropTypes.object.isRequired,
- };
-
- static propTypes = {
- intl: PropTypes.object.isRequired,
- myAccount: ImmutablePropTypes.map.isRequired,
- columns: ImmutablePropTypes.list,
- multiColumn: PropTypes.bool,
- fetchFollowRequests: PropTypes.func.isRequired,
- unreadFollowRequests: PropTypes.number,
- unreadNotifications: PropTypes.number,
- };
-
- componentDidMount() {
- const { myAccount, fetchFollowRequests, multiColumn } = this.props;
-
- if (!multiColumn && window.innerWidth >= NAVIGATION_PANEL_BREAKPOINT) {
- this.context.router.history.replace('/');
- return;
- }
-
- if (myAccount.get('locked')) {
- fetchFollowRequests();
- }
- }
-
- render() {
- const { intl, myAccount, multiColumn, unreadFollowRequests } = this.props;
-
- const navItems = [];
- let i = 1;
- let height = (multiColumn) ? 0 : 60;
-
- if (multiColumn) {
- navItems.push(
- ,
- );
-
- height += 34 + 48*2;
-
- navItems.push(
- ,
- );
-
- height += 34;
- }
-
- navItems.push(
- ,
- ,
- ,
- );
-
- height += 48*3;
-
- if (myAccount.get('locked')) {
- navItems.push();
- height += 48;
- }
-
- if (!multiColumn) {
- navItems.push(
- ,
- ,
- );
-
- height += 34 + 48;
- }
-
- return (
-
- {multiColumn &&
-
-
-
- }
-
-
-
- {!multiColumn && }
- {navItems}
-
-
- {!multiColumn &&
}
-
-
-
-
- );
- }
-
-}
diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js
index 42fbd72d4..194f2cdc0 100644
--- a/app/soapbox/features/ui/index.js
+++ b/app/soapbox/features/ui/index.js
@@ -43,7 +43,6 @@ import ProfileHoverCard from 'soapbox/components/profile_hover_card';
import {
Status,
- // GettingStarted,
CommunityTimeline,
PublicTimeline,
RemoteTimeline,
diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js
index 52400138f..cc5566937 100644
--- a/app/soapbox/features/ui/util/async-components.js
+++ b/app/soapbox/features/ui/util/async-components.js
@@ -2,10 +2,6 @@ export function EmojiPicker() {
return import(/* webpackChunkName: "emoji_picker" */'../../emoji/emoji_picker');
}
-export function Compose() {
- return import(/* webpackChunkName: "features/compose" */'../../compose');
-}
-
export function Notifications() {
return import(/* webpackChunkName: "features/notifications" */'../../notifications');
}
@@ -74,10 +70,6 @@ export function Status() {
return import(/* webpackChunkName: "features/status" */'../../status');
}
-export function GettingStarted() {
- return import(/* webpackChunkName: "features/getting_started" */'../../getting_started');
-}
-
export function PinnedStatuses() {
return import(/* webpackChunkName: "features/pinned_statuses" */'../../pinned_statuses');
}
diff --git a/package.json b/package.json
index 3701f7718..e2e5510f0 100644
--- a/package.json
+++ b/package.json
@@ -129,6 +129,7 @@
"ts-jest": "^26.4.1",
"typescript": "^4.0.3",
"uglifyjs-webpack-plugin": "^2.2.0",
+ "unused-files-webpack-plugin": "^3.4.0",
"uuid": "^8.0.0",
"webpack": "^4.41.2",
"webpack-assets-manifest": "^3.1.1",
diff --git a/webpack/shared.js b/webpack/shared.js
index f59e28c2b..c4d0aceb9 100644
--- a/webpack/shared.js
+++ b/webpack/shared.js
@@ -6,6 +6,7 @@ const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const AssetsManifestPlugin = require('webpack-assets-manifest');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const HtmlWebpackHarddiskPlugin = require('html-webpack-harddisk-plugin');
+const { UnusedFilesWebpackPlugin } = require('unused-files-webpack-plugin');
const { env, settings, output } = require('./configuration');
const rules = require('./rules');
@@ -66,6 +67,13 @@ module.exports = {
writeToDisk: true,
publicPath: true,
}),
+ // https://www.npmjs.com/package/unused-files-webpack-plugin#options
+ new UnusedFilesWebpackPlugin({
+ patterns: ['app/**/*.*'],
+ globOptions: {
+ ignore: ['node_modules/**/*', '**/__*__/**/*'],
+ },
+ }),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
template: 'app/index.ejs',
diff --git a/yarn.lock b/yarn.lock
index d85fb875a..a6d3722e6 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2778,6 +2778,14 @@ babel-runtime@^6.26.0:
core-js "^2.4.0"
regenerator-runtime "^0.11.0"
+babel-runtime@^7.0.0-beta.3:
+ version "7.0.0-beta.3"
+ resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-7.0.0-beta.3.tgz#7c750de5514452c27612172506b49085a4a630f2"
+ integrity sha512-jlzZ8RACjt0QGxq+wqsw5bCQE9RcUyWpw987mDY3GYxTpOQT2xoyNoG++oVCHzr/nACLBIprfVBNvv/If1ZYcg==
+ dependencies:
+ core-js "^2.4.0"
+ regenerator-runtime "^0.11.0"
+
backoff@^2.4.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
@@ -5570,6 +5578,14 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
+glob-all@^3.1.0:
+ version "3.2.1"
+ resolved "https://registry.yarnpkg.com/glob-all/-/glob-all-3.2.1.tgz#082ca81afd2247cbd3ed2149bb2630f4dc877d95"
+ integrity sha512-x877rVkzB3ipid577QOp+eQCR6M5ZyiwrtaYgrX/z3EThaSPFtLDwBXFHc3sH1cG0R0vFYI5SRYeWMMSEyXkUw==
+ dependencies:
+ glob "^7.1.2"
+ yargs "^15.3.1"
+
glob-parent@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae"
@@ -12211,6 +12227,17 @@ unset-value@^1.0.0:
has-value "^0.3.1"
isobject "^3.0.0"
+unused-files-webpack-plugin@^3.4.0:
+ version "3.4.0"
+ resolved "https://registry.yarnpkg.com/unused-files-webpack-plugin/-/unused-files-webpack-plugin-3.4.0.tgz#adc67a3b5549d028818d3119cbf2b5c88aea8670"
+ integrity sha512-cmukKOBdIqaM1pqThY0+jp+mYgCVyzrD8uRbKEucQwIGZcLIRn+gSRiQ7uLjcDd3Zba9NUxVGyYa7lWM4UCGeg==
+ dependencies:
+ babel-runtime "^7.0.0-beta.3"
+ glob-all "^3.1.0"
+ semver "^5.5.0"
+ util.promisify "^1.0.0"
+ warning "^3.0.0"
+
upath@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.2.tgz#3db658600edaeeccbe6db5e684d67ee8c2acd068"