diff --git a/app/soapbox/actions/settings.js b/app/soapbox/actions/settings.js index 3062e669e..55ca6b0b5 100644 --- a/app/soapbox/actions/settings.js +++ b/app/soapbox/actions/settings.js @@ -38,6 +38,8 @@ export const defaultSettings = ImmutableMap({ dyslexicFont: false, demetricator: false, + isDeveloper: false, + chats: ImmutableMap({ panes: ImmutableList(), mainWindow: 'minimized', diff --git a/app/soapbox/components/primary_navigation.js b/app/soapbox/components/primary_navigation.js index 15bc811f6..9a11e5969 100644 --- a/app/soapbox/components/primary_navigation.js +++ b/app/soapbox/components/primary_navigation.js @@ -9,6 +9,7 @@ import { NavLink, withRouter } from 'react-router-dom'; import Icon from 'soapbox/components/icon'; import IconWithCounter from 'soapbox/components/icon_with_counter'; import classNames from 'classnames'; +import { getSettings } from 'soapbox/actions/settings'; import { getFeatures } from 'soapbox/utils/features'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import { isStaff, getBaseURL } from 'soapbox/utils/accounts'; @@ -27,6 +28,7 @@ const mapStateToProps = state => { chatsCount: state.get('chats').reduce((acc, curr) => acc + Math.min(curr.get('unread', 0), 1), 0), dashboardCount: reportsCount + approvalCount, baseURL: getBaseURL(account), + settings: getSettings(state), features: getFeatures(instance), instance, }; @@ -47,13 +49,14 @@ class PrimaryNavigation extends React.PureComponent { notificationCount: PropTypes.number, chatsCount: PropTypes.number, baseURL: PropTypes.string, + settings: PropTypes.object.isRequired, features: PropTypes.object.isRequired, location: PropTypes.object, instance: ImmutablePropTypes.map.isRequired, }; render() { - const { account, features, notificationCount, chatsCount, dashboardCount, location, instance, baseURL } = this.props; + const { account, settings, features, notificationCount, chatsCount, dashboardCount, location, instance, baseURL } = this.props; return (
@@ -127,6 +130,16 @@ class PrimaryNavigation extends React.PureComponent { )} + {(settings.get('isDeveloper')) && ( + + + + + )} +
{features.federating ? ( diff --git a/app/soapbox/components/sidebar_menu.js b/app/soapbox/components/sidebar_menu.js index bfd5b9b99..4ee6fc9cd 100644 --- a/app/soapbox/components/sidebar_menu.js +++ b/app/soapbox/components/sidebar_menu.js @@ -18,6 +18,7 @@ import { logOut, switchAccount } from 'soapbox/actions/auth'; import ThemeToggle from '../features/ui/components/theme_toggle_container'; import { fetchOwnAccounts } from 'soapbox/actions/auth'; import { is as ImmutableIs } from 'immutable'; +import { getSettings } from 'soapbox/actions/settings'; import { getSoapboxConfig } from 'soapbox/actions/soapbox'; import { getFeatures } from 'soapbox/utils/features'; @@ -45,6 +46,7 @@ const messages = defineMessages({ donate: { id: 'donate', defaultMessage: 'Donate' }, donate_crypto: { id: 'donate_crypto', defaultMessage: 'Donate cryptocurrency' }, info: { id: 'column.info', defaultMessage: 'Server information' }, + developers: { id: 'navigation.developers', defaultMessage: 'Developers' }, add_account: { id: 'profile_dropdown.add_account', defaultMessage: 'Add an existing account' }, }); @@ -67,6 +69,7 @@ const makeMapStateToProps = () => { hasCrypto: typeof soapbox.getIn(['cryptoAddresses', 0, 'ticker']) === 'string', otherAccounts: getOtherAccounts(state), features, + settings: getSettings(state), siteTitle: instance.get('title'), baseURL: getBaseURL(account), }; @@ -101,6 +104,7 @@ class SidebarMenu extends ImmutablePureComponent { otherAccounts: ImmutablePropTypes.list, sidebarOpen: PropTypes.bool, onClose: PropTypes.func.isRequired, + settings: PropTypes.object.isRequired, features: PropTypes.object.isRequired, baseURL: PropTypes.string, }; @@ -159,7 +163,7 @@ class SidebarMenu extends ImmutablePureComponent { } render() { - const { sidebarOpen, intl, account, onClickLogOut, donateUrl, otherAccounts, hasCrypto, features, siteTitle, baseURL } = this.props; + const { sidebarOpen, intl, account, onClickLogOut, donateUrl, otherAccounts, hasCrypto, settings, features, siteTitle, baseURL } = this.props; const { switcher } = this.state; if (!account) return null; const acct = account.get('acct'); @@ -319,6 +323,13 @@ class SidebarMenu extends ImmutablePureComponent {
+ {(settings.get('isDeveloper')) && ( + + + {intl.formatMessage(messages.developers)} + + )} +
diff --git a/app/soapbox/features/developers/index.js b/app/soapbox/features/developers/index.js new file mode 100644 index 000000000..cc74e5c14 --- /dev/null +++ b/app/soapbox/features/developers/index.js @@ -0,0 +1,29 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { injectIntl, defineMessages } from 'react-intl'; +import Column from '../ui/components/column'; + +const messages = defineMessages({ + heading: { id: 'column.developers', defaultMessage: 'Developers' }, +}); + +export default @injectIntl +class Developers extends React.Component { + + static propTypes = { + intl: PropTypes.object.isRequired, + } + + render() { + const { intl } = this.props; + + return ( + +
+ WIP: Developers page +
+
+ ); + } + +} diff --git a/app/soapbox/features/preferences/index.js b/app/soapbox/features/preferences/index.js index e95a79eda..14e41fbfe 100644 --- a/app/soapbox/features/preferences/index.js +++ b/app/soapbox/features/preferences/index.js @@ -262,6 +262,10 @@ class Preferences extends ImmutablePureComponent { hint={} path={['demetricator']} /> + } + path={['isDeveloper']} + /> diff --git a/app/soapbox/features/ui/index.js b/app/soapbox/features/ui/index.js index a16b12bf3..924c5a757 100644 --- a/app/soapbox/features/ui/index.js +++ b/app/soapbox/features/ui/index.js @@ -115,6 +115,7 @@ import { Share, NewStatus, IntentionalError, + Developers, } from './util/async-components'; // Dummy import, to make sure that ends up in the application bundle. @@ -318,7 +319,9 @@ class SwitchingColumnsArea extends React.PureComponent { + + diff --git a/app/soapbox/features/ui/util/async-components.js b/app/soapbox/features/ui/util/async-components.js index 2223eeb92..9bd0418b6 100644 --- a/app/soapbox/features/ui/util/async-components.js +++ b/app/soapbox/features/ui/util/async-components.js @@ -425,3 +425,7 @@ export function NewStatus() { export function IntentionalError() { return import(/* webpackChunkName: "error" */'../../intentional_error'); } + +export function Developers() { + return import(/* webpackChunkName: "features/developers" */'../../developers'); +} diff --git a/app/styles/components/icon.scss b/app/styles/components/icon.scss index 3514ab03a..b49c5412e 100644 --- a/app/styles/components/icon.scss +++ b/app/styles/components/icon.scss @@ -18,7 +18,8 @@ fill: currentColor; } - svg.icon-tabler-search { + svg.icon-tabler-search, + svg.icon-tabler-code { stroke-width: 2.3px; } diff --git a/app/styles/navigation.scss b/app/styles/navigation.scss index c14a3cf33..0dcb07a4c 100644 --- a/app/styles/navigation.scss +++ b/app/styles/navigation.scss @@ -18,7 +18,8 @@ } &--active { - svg.icon-tabler-search { + svg.icon-tabler-search, + svg.icon-tabler-code { stroke-width: 2.5px; } }