diff --git a/app/javascript/flavours/glitch/actions/rules.js b/app/javascript/flavours/glitch/actions/rules.js
deleted file mode 100644
index b95045e81..000000000
--- a/app/javascript/flavours/glitch/actions/rules.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import api from 'flavours/glitch/util/api';
-
-export const RULES_FETCH_REQUEST = 'RULES_FETCH_REQUEST';
-export const RULES_FETCH_SUCCESS = 'RULES_FETCH_SUCCESS';
-export const RULES_FETCH_FAIL = 'RULES_FETCH_FAIL';
-
-export const fetchRules = () => (dispatch, getState) => {
- dispatch(fetchRulesRequest());
-
- api(getState)
- .get('/api/v1/instance').then(({ data }) => dispatch(fetchRulesSuccess(data.rules)))
- .catch(err => dispatch(fetchRulesFail(err)));
-};
-
-const fetchRulesRequest = () => ({
- type: RULES_FETCH_REQUEST,
-});
-
-const fetchRulesSuccess = rules => ({
- type: RULES_FETCH_SUCCESS,
- rules,
-});
-
-const fetchRulesFail = error => ({
- type: RULES_FETCH_FAIL,
- error,
-});
diff --git a/app/javascript/flavours/glitch/actions/server.js b/app/javascript/flavours/glitch/actions/server.js
new file mode 100644
index 000000000..215dfeffa
--- /dev/null
+++ b/app/javascript/flavours/glitch/actions/server.js
@@ -0,0 +1,30 @@
+import api from 'flavours/glitch/util/api';
+import { importFetchedAccount } from './importer';
+
+export const SERVER_FETCH_REQUEST = 'Server_FETCH_REQUEST';
+export const SERVER_FETCH_SUCCESS = 'Server_FETCH_SUCCESS';
+export const SERVER_FETCH_FAIL = 'Server_FETCH_FAIL';
+
+export const fetchServer = () => (dispatch, getState) => {
+ dispatch(fetchServerRequest());
+
+ api(getState)
+ .get('/api/v2/instance').then(({ data }) => {
+ if (data.contact.account) dispatch(importFetchedAccount(data.contact.account));
+ dispatch(fetchServerSuccess(data));
+ }).catch(err => dispatch(fetchServerFail(err)));
+};
+
+const fetchServerRequest = () => ({
+ type: SERVER_FETCH_REQUEST,
+});
+
+const fetchServerSuccess = server => ({
+ type: SERVER_FETCH_SUCCESS,
+ server,
+});
+
+const fetchServerFail = error => ({
+ type: SERVER_FETCH_FAIL,
+ error,
+});
diff --git a/app/javascript/flavours/glitch/components/account.js b/app/javascript/flavours/glitch/components/account.js
index 489f60736..24d3f65ef 100644
--- a/app/javascript/flavours/glitch/components/account.js
+++ b/app/javascript/flavours/glitch/components/account.js
@@ -9,6 +9,7 @@ import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { me } from 'flavours/glitch/util/initial_state';
import RelativeTimestamp from './relative_timestamp';
+import Skeleton from 'flavours/glitch/components/skeleton';
const messages = defineMessages({
follow: { id: 'account.follow', defaultMessage: 'Follow' },
@@ -26,7 +27,7 @@ export default @injectIntl
class Account extends ImmutablePureComponent {
static propTypes = {
- account: ImmutablePropTypes.map.isRequired,
+ account: ImmutablePropTypes.map,
onFollow: PropTypes.func.isRequired,
onBlock: PropTypes.func.isRequired,
onMute: PropTypes.func.isRequired,
@@ -77,7 +78,16 @@ class Account extends ImmutablePureComponent {
} = this.props;
if (!account) {
- return
;
+ return (
+
+ );
}
if (hidden) {
diff --git a/app/javascript/flavours/glitch/components/display_name.js b/app/javascript/flavours/glitch/components/display_name.js
index 9c7da744e..7cb0c9133 100644
--- a/app/javascript/flavours/glitch/components/display_name.js
+++ b/app/javascript/flavours/glitch/components/display_name.js
@@ -3,6 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types';
import classNames from 'classnames';
import { autoPlayGif } from 'flavours/glitch/util/initial_state';
+import Skeleton from 'flavours/glitch/components/skeleton';
export default class DisplayName extends React.PureComponent {
@@ -46,14 +47,15 @@ export default class DisplayName extends React.PureComponent {
const computedClass = classNames('display-name', { inline }, className);
- if (!account) return null;
-
let displayName, suffix;
+ let acct;
- let acct = account.get('acct');
+ if (account) {
+ acct = account.get('acct');
- if (acct.indexOf('@') === -1 && localDomain) {
- acct = `${acct}@${localDomain}`;
+ if (acct.indexOf('@') === -1 && localDomain) {
+ acct = `${acct}@${localDomain}`;
+ }
}
if (others && others.size > 0) {
@@ -80,9 +82,12 @@ export default class DisplayName extends React.PureComponent {
@{acct}
);
- } else {
+ } else if (account) {
displayName = ;
suffix = @{acct};
+ } else {
+ displayName = ;
+ suffix = ;
}
return (
diff --git a/app/javascript/flavours/glitch/components/server_banner.js b/app/javascript/flavours/glitch/components/server_banner.js
new file mode 100644
index 000000000..e29876d4b
--- /dev/null
+++ b/app/javascript/flavours/glitch/components/server_banner.js
@@ -0,0 +1,91 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { domain } from 'flavours/glitch/util/initial_state';
+import { fetchServer } from 'flavours/glitch/actions/server';
+import { connect } from 'react-redux';
+import Account from 'flavours/glitch/containers/account_container';
+import ShortNumber from 'flavours/glitch/components/short_number';
+import Skeleton from 'flavours/glitch/components/skeleton';
+import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+ aboutActiveUsers: { id: 'server_banner.about_active_users', defaultMessage: 'People using this server during the last 30 days (Monthly Active Users)' },
+});
+
+const mapStateToProps = state => ({
+ server: state.get('server'),
+});
+
+export default @connect(mapStateToProps)
+@injectIntl
+class ServerBanner extends React.PureComponent {
+
+ static propTypes = {
+ server: PropTypes.object,
+ dispatch: PropTypes.func,
+ intl: PropTypes.object,
+ };
+
+ componentDidMount () {
+ const { dispatch } = this.props;
+ dispatch(fetchServer());
+ }
+
+ render () {
+ const { server, intl } = this.props;
+ const isLoading = server.get('isLoading');
+
+ return (
+
+
+
+
+
+
+ {isLoading ? (
+ <>
+
+
+
+
+
+ >
+ ) : server.get('description')}
+
+
+
+
+
+
+
+
+ {isLoading ? (
+ <>
+
+
+
+ >
+ ) : (
+ <>
+
+
+
+ >
+ )}
+
+
+
+
+
+
+
+ );
+ }
+
+}
diff --git a/app/javascript/flavours/glitch/features/report/rules.js b/app/javascript/flavours/glitch/features/report/rules.js
index 4772e04a2..599c04dbd 100644
--- a/app/javascript/flavours/glitch/features/report/rules.js
+++ b/app/javascript/flavours/glitch/features/report/rules.js
@@ -7,7 +7,7 @@ import Button from 'flavours/glitch/components/button';
import Option from './components/option';
const mapStateToProps = state => ({
- rules: state.get('rules'),
+ rules: state.getIn(['server', 'rules']),
});
export default @connect(mapStateToProps)
diff --git a/app/javascript/flavours/glitch/features/ui/components/compose_panel.js b/app/javascript/flavours/glitch/features/ui/components/compose_panel.js
index 298c15a8a..6e1c51d74 100644
--- a/app/javascript/flavours/glitch/features/ui/components/compose_panel.js
+++ b/app/javascript/flavours/glitch/features/ui/components/compose_panel.js
@@ -4,6 +4,7 @@ import SearchContainer from 'flavours/glitch/features/compose/containers/search_
import ComposeFormContainer from 'flavours/glitch/features/compose/containers/compose_form_container';
import NavigationContainer from 'flavours/glitch/features/compose/containers/navigation_container';
import LinkFooter from './link_footer';
+import ServerBanner from 'flavours/glitch/components/server_banner';
export default
class ComposePanel extends React.PureComponent {
@@ -21,6 +22,7 @@ class ComposePanel extends React.PureComponent {
{!signedIn && (
+
)}
diff --git a/app/javascript/flavours/glitch/features/ui/components/report_modal.js b/app/javascript/flavours/glitch/features/ui/components/report_modal.js
index dcbe94929..7b6a4a784 100644
--- a/app/javascript/flavours/glitch/features/ui/components/report_modal.js
+++ b/app/javascript/flavours/glitch/features/ui/components/report_modal.js
@@ -2,7 +2,7 @@ import React from 'react';
import { connect } from 'react-redux';
import { submitReport } from 'flavours/glitch/actions/reports';
import { expandAccountTimeline } from 'flavours/glitch/actions/timelines';
-import { fetchRules } from 'flavours/glitch/actions/rules';
+import { fetchServer } from 'flavours/glitch/actions/server';
import { fetchRelationships } from 'flavours/glitch/actions/accounts';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
@@ -119,7 +119,7 @@ class ReportModal extends ImmutablePureComponent {
dispatch(fetchRelationships([accountId]));
dispatch(expandAccountTimeline(accountId, { withReplies: true }));
- dispatch(fetchRules());
+ dispatch(fetchServer());
}
render () {
diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js
index 6c60a86c4..735623e3d 100644
--- a/app/javascript/flavours/glitch/features/ui/index.js
+++ b/app/javascript/flavours/glitch/features/ui/index.js
@@ -10,7 +10,7 @@ import { debounce } from 'lodash';
import { uploadCompose, resetCompose, changeComposeSpoilerness } from 'flavours/glitch/actions/compose';
import { expandHomeTimeline } from 'flavours/glitch/actions/timelines';
import { expandNotifications, notificationsSetVisibility } from 'flavours/glitch/actions/notifications';
-import { fetchRules } from 'flavours/glitch/actions/rules';
+import { fetchServer } from 'flavours/glitch/actions/server';
import { clearHeight } from 'flavours/glitch/actions/height_cache';
import { changeLayout } from 'flavours/glitch/actions/app';
import { synchronouslySubmitMarkers, submitMarkers, fetchMarkers } from 'flavours/glitch/actions/markers';
@@ -408,7 +408,7 @@ class UI extends React.Component {
this.props.dispatch(expandHomeTimeline());
this.props.dispatch(expandNotifications());
- setTimeout(() => this.props.dispatch(fetchRules()), 3000);
+ setTimeout(() => this.props.dispatch(fetchServer()), 3000);
}
this.hotkeys.__mousetrap__.stopCallback = (e, element) => {
diff --git a/app/javascript/flavours/glitch/reducers/index.js b/app/javascript/flavours/glitch/reducers/index.js
index 991b4aa79..09c08a362 100644
--- a/app/javascript/flavours/glitch/reducers/index.js
+++ b/app/javascript/flavours/glitch/reducers/index.js
@@ -17,7 +17,7 @@ import push_notifications from './push_notifications';
import status_lists from './status_lists';
import mutes from './mutes';
import blocks from './blocks';
-import rules from './rules';
+import server from './server';
import boosts from './boosts';
import contexts from './contexts';
import compose from './compose';
@@ -64,7 +64,7 @@ const reducers = {
push_notifications,
mutes,
blocks,
- rules,
+ server,
boosts,
contexts,
compose,
diff --git a/app/javascript/flavours/glitch/reducers/rules.js b/app/javascript/flavours/glitch/reducers/rules.js
deleted file mode 100644
index 6cc2230bc..000000000
--- a/app/javascript/flavours/glitch/reducers/rules.js
+++ /dev/null
@@ -1,13 +0,0 @@
-import { RULES_FETCH_SUCCESS } from 'flavours/glitch/actions/rules';
-import { List as ImmutableList, fromJS } from 'immutable';
-
-const initialState = ImmutableList();
-
-export default function rules(state = initialState, action) {
- switch (action.type) {
- case RULES_FETCH_SUCCESS:
- return fromJS(action.rules);
- default:
- return state;
- }
-}
diff --git a/app/javascript/flavours/glitch/reducers/server.js b/app/javascript/flavours/glitch/reducers/server.js
new file mode 100644
index 000000000..977574148
--- /dev/null
+++ b/app/javascript/flavours/glitch/reducers/server.js
@@ -0,0 +1,19 @@
+import { SERVER_FETCH_REQUEST, SERVER_FETCH_SUCCESS, SERVER_FETCH_FAIL } from 'flavours/glitch/actions/server';
+import { Map as ImmutableMap, fromJS } from 'immutable';
+
+const initialState = ImmutableMap({
+ isLoading: true,
+});
+
+export default function server(state = initialState, action) {
+ switch (action.type) {
+ case SERVER_FETCH_REQUEST:
+ return state.set('isLoading', true);
+ case SERVER_FETCH_SUCCESS:
+ return fromJS(action.server).set('isLoading', false);
+ case SERVER_FETCH_FAIL:
+ return state.set('isLoading', false);
+ default:
+ return state;
+ }
+}
diff --git a/app/javascript/flavours/glitch/styles/components/signed_out.scss b/app/javascript/flavours/glitch/styles/components/signed_out.scss
index 74eccf497..a318bf66b 100644
--- a/app/javascript/flavours/glitch/styles/components/signed_out.scss
+++ b/app/javascript/flavours/glitch/styles/components/signed_out.scss
@@ -10,3 +10,85 @@
margin-bottom: 10px;
}
}
+
+.server-banner {
+ padding: 20px 0;
+
+ &__introduction {
+ color: $darker-text-color;
+ margin-bottom: 20px;
+
+ strong {
+ font-weight: 600;
+ }
+
+ a {
+ color: inherit;
+ text-decoration: underline;
+
+ &:hover,
+ &:active,
+ &:focus {
+ text-decoration: none;
+ }
+ }
+ }
+
+ &__hero {
+ display: block;
+ border-radius: 4px;
+ width: 100%;
+ height: auto;
+ margin-bottom: 20px;
+ aspect-ratio: 1.9;
+ border: 0;
+ background: $ui-base-color;
+ object-fit: cover;
+ }
+
+ &__description {
+ margin-bottom: 20px;
+ }
+
+ &__meta {
+ display: flex;
+ gap: 10px;
+ max-width: 100%;
+
+ &__column {
+ flex: 0 0 auto;
+ width: calc(50% - 5px);
+ overflow: hidden;
+ }
+ }
+
+ &__number {
+ font-weight: 600;
+ color: $primary-text-color;
+ }
+
+ &__number-label {
+ color: $darker-text-color;
+ font-weight: 500;
+ }
+
+ h4 {
+ text-transform: uppercase;
+ color: $darker-text-color;
+ margin-bottom: 10px;
+ font-weight: 600;
+ }
+
+ .account {
+ padding: 0;
+ border: 0;
+ }
+
+ .account__avatar-wrapper {
+ margin-left: 0;
+ }
+
+ .spacer {
+ margin: 10px 0;
+ }
+}
diff --git a/app/javascript/flavours/glitch/util/initial_state.js b/app/javascript/flavours/glitch/util/initial_state.js
index b02a52ea5..99ee6bc69 100644
--- a/app/javascript/flavours/glitch/util/initial_state.js
+++ b/app/javascript/flavours/glitch/util/initial_state.js
@@ -40,6 +40,5 @@ export const showTrends = getMeta('trends');
export const title = getMeta('title');
export const disableSwiping = getMeta('disable_swiping');
export const languages = initialState && initialState.languages;
-export const server = initialState && initialState.server;
export default initialState;