From 0ff1d62c7a5f6b62799a028364b819a5b0686af1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 29 Sep 2022 04:39:33 +0200 Subject: [PATCH] [Glitch] Add logged-out access to the web UI Port part of 43b5d5e38d2b8ad8f1d1ad0911c3c1718159c912 to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/actions/accounts.js | 6 +- .../flavours/glitch/actions/markers.js | 10 ++- .../flavours/glitch/containers/mastodon.js | 2 +- .../features/account/components/header.js | 15 ++-- .../glitch/features/explore/results.js | 12 ++- .../glitch/features/hashtag_timeline/index.js | 12 ++- .../features/ui/components/columns_area.js | 4 +- .../features/ui/components/compose_panel.js | 42 +++++++-- .../features/ui/components/link_footer.js | 48 +++++++++-- .../ui/components/navigation_panel.js | 85 ++++++++++++++----- .../features/ui/components/sign_in_banner.js | 11 +++ .../flavours/glitch/features/ui/index.js | 37 ++++++-- .../flavours/glitch/styles/_mixins.scss | 1 + .../glitch/styles/components/columns.scss | 14 +++ .../glitch/styles/components/index.scss | 2 + .../glitch/styles/components/signed_out.scss | 8 ++ .../styles/components/single_column.scss | 32 ++++++- .../flavours/glitch/util/initial_state.js | 2 + 18 files changed, 275 insertions(+), 68 deletions(-) create mode 100644 app/javascript/flavours/glitch/features/ui/components/sign_in_banner.js create mode 100644 app/javascript/flavours/glitch/styles/components/signed_out.scss diff --git a/app/javascript/flavours/glitch/actions/accounts.js b/app/javascript/flavours/glitch/actions/accounts.js index f5871beb3..750740879 100644 --- a/app/javascript/flavours/glitch/actions/accounts.js +++ b/app/javascript/flavours/glitch/actions/accounts.js @@ -553,10 +553,12 @@ export function expandFollowingFail(id, error) { export function fetchRelationships(accountIds) { return (dispatch, getState) => { - const loadedRelationships = getState().get('relationships'); + const state = getState(); + const loadedRelationships = state.get('relationships'); const newAccountIds = accountIds.filter(id => loadedRelationships.get(id, null) === null); + const signedIn = !!state.getIn(['meta', 'me']); - if (newAccountIds.length === 0) { + if (!signedIn || newAccountIds.length === 0) { return; } diff --git a/app/javascript/flavours/glitch/actions/markers.js b/app/javascript/flavours/glitch/actions/markers.js index a086def97..6a0549f7f 100644 --- a/app/javascript/flavours/glitch/actions/markers.js +++ b/app/javascript/flavours/glitch/actions/markers.js @@ -1,6 +1,7 @@ import api from 'flavours/glitch/util/api'; import { debounce } from 'lodash'; import compareId from 'flavours/glitch/util/compare_id'; +import { List as ImmutableList } from 'immutable'; export const MARKERS_FETCH_REQUEST = 'MARKERS_FETCH_REQUEST'; export const MARKERS_FETCH_SUCCESS = 'MARKERS_FETCH_SUCCESS'; @@ -11,7 +12,7 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => { const accessToken = getState().getIn(['meta', 'access_token'], ''); const params = _buildParams(getState()); - if (Object.keys(params).length === 0) { + if (Object.keys(params).length === 0 || accessToken === '') { return; } @@ -63,7 +64,7 @@ export const synchronouslySubmitMarkers = () => (dispatch, getState) => { const _buildParams = (state) => { const params = {}; - const lastHomeId = state.getIn(['timelines', 'home', 'items']).find(item => item !== null); + const lastHomeId = state.getIn(['timelines', 'home', 'items'], ImmutableList()).find(item => item !== null); const lastNotificationId = state.getIn(['notifications', 'lastReadId']); if (lastHomeId && compareId(lastHomeId, state.getIn(['markers', 'home'])) > 0) { @@ -82,9 +83,10 @@ const _buildParams = (state) => { }; const debouncedSubmitMarkers = debounce((dispatch, getState) => { - const params = _buildParams(getState()); + const accessToken = getState().getIn(['meta', 'access_token'], ''); + const params = _buildParams(getState()); - if (Object.keys(params).length === 0) { + if (Object.keys(params).length === 0 || accessToken === '') { return; } diff --git a/app/javascript/flavours/glitch/containers/mastodon.js b/app/javascript/flavours/glitch/containers/mastodon.js index d07b2b3d0..a6ec5845d 100644 --- a/app/javascript/flavours/glitch/containers/mastodon.js +++ b/app/javascript/flavours/glitch/containers/mastodon.js @@ -31,7 +31,7 @@ const createIdentityContext = state => ({ signedIn: !!state.meta.me, accountId: state.meta.me, accessToken: state.meta.access_token, - permissions: state.role.permissions, + permissions: state.role ? state.role.permissions : 0, }); export default class Mastodon extends React.PureComponent { diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index cc2a7d4d4..866122cbd 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -124,6 +124,7 @@ class Header extends ImmutablePureComponent { render () { const { account, hidden, intl, domain } = this.props; + const { signedIn } = this.context.identity; if (!account) { return null; @@ -157,12 +158,12 @@ class Header extends ImmutablePureComponent { } if (me !== account.get('id')) { - if (!account.get('relationship')) { // Wait until the relationship is loaded + if (signedIn && !account.get('relationship')) { // Wait until the relationship is loaded actionBtn = ''; } else if (account.getIn(['relationship', 'requested'])) { actionBtn = ); diff --git a/app/javascript/flavours/glitch/features/ui/components/columns_area.js b/app/javascript/flavours/glitch/features/ui/components/columns_area.js index 048251fa6..5f5018105 100644 --- a/app/javascript/flavours/glitch/features/ui/components/columns_area.js +++ b/app/javascript/flavours/glitch/features/ui/components/columns_area.js @@ -60,6 +60,7 @@ class ColumnsArea extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object.isRequired, + identity: PropTypes.object.isRequired, }; static propTypes = { @@ -213,11 +214,12 @@ class ColumnsArea extends ImmutablePureComponent { render () { const { columns, children, singleColumn, intl, navbarUnder, openSettings } = this.props; const { shouldAnimate, renderComposePanel } = this.state; + const { signedIn } = this.context.identity; const columnIndex = getIndex(this.context.router.history.location.pathname); if (singleColumn) { - const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : ; + const floatingActionButton = (!signedIn || shouldHideFAB(this.context.router.history.location.pathname)) ? null : ; const content = columnIndex !== -1 ? ( 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 498f09ab6..298c15a8a 100644 --- a/app/javascript/flavours/glitch/features/ui/components/compose_panel.js +++ b/app/javascript/flavours/glitch/features/ui/components/compose_panel.js @@ -1,16 +1,40 @@ import React from 'react'; +import PropTypes from 'prop-types'; import SearchContainer from 'flavours/glitch/features/compose/containers/search_container'; 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'; -const ComposePanel = () => ( -
- - - - -
-); +export default +class ComposePanel extends React.PureComponent { -export default ComposePanel; + static contextTypes = { + identity: PropTypes.object.isRequired, + }; + + render() { + const { signedIn } = this.context.identity; + + return ( +
+ + + {!signedIn && ( + +
+ + )} + + {signedIn && ( + + + + + )} + + +
+ ); + } + +}; diff --git a/app/javascript/flavours/glitch/features/ui/components/link_footer.js b/app/javascript/flavours/glitch/features/ui/components/link_footer.js index 67fa067f9..bb8f89e0f 100644 --- a/app/javascript/flavours/glitch/features/ui/components/link_footer.js +++ b/app/javascript/flavours/glitch/features/ui/components/link_footer.js @@ -48,18 +48,48 @@ class LinkFooter extends React.PureComponent { } render () { + const { signedIn, permissions } = this.context.identity; + + const items = []; + + if ((this.context.identity.permissions & PERMISSION_INVITE_USERS) === PERMISSION_INVITE_USERS) { + items.push(); + } + + if (signedIn && securityLink) { + items.push(); + } + + if (!limitedFederationMode) { + items.push(); + } + + if (profileDirectory) { + items.push(); + } + + items.push(); + + if (privacyPolicyLink) { + items.push(); + } + + if (signedIn) { + items.push(); + } + + items.push(); + + if (signedIn) { + items.push(); + } + return (
    - {((this.context.identity.permissions & PERMISSION_INVITE_USERS) === PERMISSION_INVITE_USERS) &&
  • ·
  • } - {!!securityLink &&
  • ·
  • } - {!limitedFederationMode &&
  • ·
  • } - {profileDirectory &&
  • ·
  • } -
  • ·
  • -
  • ·
  • -
  • ·
  • -
  • ·
  • -
  • + {items.map((item, index, array) => ( +
  • {item} { index === array.length - 1 ? null : ' · ' }
  • + ))}

diff --git a/app/javascript/flavours/glitch/features/ui/components/navigation_panel.js b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.js index f4d649456..453276775 100644 --- a/app/javascript/flavours/glitch/features/ui/components/navigation_panel.js +++ b/app/javascript/flavours/glitch/features/ui/components/navigation_panel.js @@ -1,5 +1,6 @@ import React from 'react'; -import { NavLink, withRouter } from 'react-router-dom'; +import PropTypes from 'prop-types'; +import { NavLink, Link } from 'react-router-dom'; import { FormattedMessage } from 'react-intl'; import Icon from 'flavours/glitch/components/icon'; import { showTrends } from 'flavours/glitch/util/initial_state'; @@ -8,30 +9,70 @@ import NotificationsCounterIcon from './notifications_counter_icon'; import FollowRequestsNavLink from './follow_requests_nav_link'; import ListPanel from './list_panel'; import TrendsContainer from 'flavours/glitch/features/getting_started/containers/trends_container'; +import SignInBanner from './sign_in_banner'; -const NavigationPanel = ({ onOpenSettings }) => ( -

- - - - { showTrends && } - - - - - +export default class NavigationPanel extends React.Component { - + static contextTypes = { + router: PropTypes.object.isRequired, + identity: PropTypes.object.isRequired, + }; -
+ static propTypes = { + onOpenSettings: PropTypes.func, + }; - {!!preferencesLink && } - - {!!relationshipsLink && } + render() { + const { signedIn } = this.context.identity; + const { onOpenSettings } = this.props; - {showTrends &&
} - {showTrends && } -
-); + return ( +
+ {signedIn && ( + + + + + + )} -export default withRouter(NavigationPanel); + { showTrends && } + + + + + {!signedIn && ( + +
+ +
+ )} + + {signedIn && ( + + + + + + + +
+ + {!!preferencesLink && } + + {!!relationshipsLink && } +
+ )} + + {showTrends && ( + +
+ + + )} + +
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/ui/components/sign_in_banner.js b/app/javascript/flavours/glitch/features/ui/components/sign_in_banner.js new file mode 100644 index 000000000..c8403a8ad --- /dev/null +++ b/app/javascript/flavours/glitch/features/ui/components/sign_in_banner.js @@ -0,0 +1,11 @@ +import React from 'react'; +import { FormattedMessage } from 'react-intl'; + +const SignInBanner = () => ( +
+

+ +
+); + +export default SignInBanner; diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js index 7b547fd5b..15661914b 100644 --- a/app/javascript/flavours/glitch/features/ui/index.js +++ b/app/javascript/flavours/glitch/features/ui/index.js @@ -121,6 +121,10 @@ const keyMap = { class SwitchingColumnsArea extends React.PureComponent { + static contextTypes = { + identity: PropTypes.object, + }; + static propTypes = { children: PropTypes.node, location: PropTypes.object, @@ -157,12 +161,25 @@ class SwitchingColumnsArea extends React.PureComponent { render () { const { children, mobile, navbarUnder } = this.props; - const redirect = mobile ? : ; + const { signedIn } = this.context.identity; + + let redirect; + + if (signedIn) { + if (mobile) { + redirect = ; + } else { + redirect = ; + } + } else { + redirect = ; + } return ( {redirect} + @@ -219,6 +236,10 @@ export default @connect(mapStateToProps) @withRouter class UI extends React.Component { + static contextTypes = { + identity: PropTypes.object.isRequired, + }; + static propTypes = { dispatch: PropTypes.func.isRequired, children: PropTypes.node, @@ -358,6 +379,8 @@ class UI extends React.Component { } componentDidMount () { + const { signedIn } = this.context.identity; + window.addEventListener('beforeunload', this.handleBeforeUnload, false); window.addEventListener('resize', this.handleResize, { passive: true }); @@ -374,16 +397,18 @@ class UI extends React.Component { this.favicon = new Favico({ animation:"none" }); // On first launch, redirect to the follow recommendations page - if (this.props.firstLaunch) { + if (signedIn && this.props.firstLaunch) { this.context.router.history.replace('/start'); this.props.dispatch(closeOnboarding()); } - this.props.dispatch(fetchMarkers()); - this.props.dispatch(expandHomeTimeline()); - this.props.dispatch(expandNotifications()); + if (signedIn) { + this.props.dispatch(fetchMarkers()); + this.props.dispatch(expandHomeTimeline()); + this.props.dispatch(expandNotifications()); - setTimeout(() => this.props.dispatch(fetchRules()), 3000); + setTimeout(() => this.props.dispatch(fetchRules()), 3000); + } this.hotkeys.__mousetrap__.stopCallback = (e, element) => { return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName); diff --git a/app/javascript/flavours/glitch/styles/_mixins.scss b/app/javascript/flavours/glitch/styles/_mixins.scss index c92bc8608..9f6314f3f 100644 --- a/app/javascript/flavours/glitch/styles/_mixins.scss +++ b/app/javascript/flavours/glitch/styles/_mixins.scss @@ -60,6 +60,7 @@ font-family: inherit; background: $ui-base-color; color: $darker-text-color; + border-radius: 4px; font-size: 14px; margin: 0; } diff --git a/app/javascript/flavours/glitch/styles/components/columns.scss b/app/javascript/flavours/glitch/styles/components/columns.scss index 1440682f3..f5b712499 100644 --- a/app/javascript/flavours/glitch/styles/components/columns.scss +++ b/app/javascript/flavours/glitch/styles/components/columns.scss @@ -117,6 +117,7 @@ box-sizing: border-box; width: 100%; background: lighten($ui-base-color, 4%); + border-radius: 4px 4px 0 0; color: $highlight-text-color; cursor: pointer; flex: 0 0 auto; @@ -204,6 +205,17 @@ color: $highlight-text-color; } } + + &--logo { + background: transparent; + padding: 10px; + + &:hover, + &:focus, + &:active { + background: transparent; + } + } } .column-link__icon { @@ -255,6 +267,7 @@ display: flex; font-size: 16px; background: lighten($ui-base-color, 4%); + border-radius: 4px 4px 0 0; flex: 0 0 auto; cursor: pointer; position: relative; @@ -309,6 +322,7 @@ > .scrollable { background: $ui-base-color; + border-radius: 0 0 4px 4px; } } diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index 14fbc61b5..cf5339d36 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -110,6 +110,7 @@ &:hover { border-color: lighten($ui-primary-color, 4%); color: lighten($darker-text-color, 4%); + text-decoration: none; } &:disabled { @@ -1756,3 +1757,4 @@ noscript { @import 'single_column'; @import 'announcements'; @import 'explore'; +@import 'signed_out'; diff --git a/app/javascript/flavours/glitch/styles/components/signed_out.scss b/app/javascript/flavours/glitch/styles/components/signed_out.scss new file mode 100644 index 000000000..2b5cccd92 --- /dev/null +++ b/app/javascript/flavours/glitch/styles/components/signed_out.scss @@ -0,0 +1,8 @@ +.sign-in-banner { + padding: 10px; + + p { + color: $darker-text-color; + margin-bottom: 20px; + } +} diff --git a/app/javascript/flavours/glitch/styles/components/single_column.scss b/app/javascript/flavours/glitch/styles/components/single_column.scss index 3843bcd68..bbb8b456c 100644 --- a/app/javascript/flavours/glitch/styles/components/single_column.scss +++ b/app/javascript/flavours/glitch/styles/components/single_column.scss @@ -6,6 +6,26 @@ height: calc(100% - 10px); overflow-y: hidden; + .hero-widget { + box-shadow: none; + + &__text, + &__img, + &__img img { + border-radius: 0; + } + + &__text { + padding: 15px; + color: $secondary-text-color; + + strong { + font-weight: 700; + color: $primary-text-color; + } + } + } + .search__input { line-height: 18px; font-size: 16px; @@ -21,10 +41,6 @@ flex: 0 1 48px; } - .flex-spacer { - background: transparent; - } - .composer { flex: 1; overflow-y: hidden; @@ -61,6 +77,14 @@ flex: 0 0 auto; } + .logo { + height: 30px; + width: auto; + } +} + +.navigation-panel, +.compose-panel { hr { flex: 0 0 auto; border: 0; diff --git a/app/javascript/flavours/glitch/util/initial_state.js b/app/javascript/flavours/glitch/util/initial_state.js index 90dada4b3..30f789a06 100644 --- a/app/javascript/flavours/glitch/util/initial_state.js +++ b/app/javascript/flavours/glitch/util/initial_state.js @@ -11,6 +11,7 @@ const initialState = element && function () { const getMeta = (prop) => initialState && initialState.meta && initialState.meta[prop]; +export const domain = getMeta('domain'); export const reduceMotion = getMeta('reduce_motion'); export const autoPlayGif = getMeta('auto_play_gif'); export const displayMedia = getMeta('display_media') || (getMeta('display_sensitive_media') ? 'show_all' : 'default'); @@ -37,5 +38,6 @@ export const useSystemEmojiFont = getMeta('system_emoji_font'); export const showTrends = getMeta('trends'); export const disableSwiping = getMeta('disable_swiping'); export const languages = initialState && initialState.languages; +export const server = initialState && initialState.server; export default initialState;