From 89bc4dff6f85e585713e777b4a860df77db2936e Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Mon, 19 Apr 2021 14:45:15 +0200 Subject: [Glitch] Change onboarding by replacing tutorial with follow recommendations in web UI Port bf903dc51070f952ab64e43918e803fdaaa15e4d to glitch-soc Signed-off-by: Claire --- .../follow_recommendations/components/account.js | 85 +++++++++++++++++++ .../features/follow_recommendations/index.js | 95 ++++++++++++++++++++++ .../flavours/glitch/features/ui/index.js | 11 +++ 3 files changed, 191 insertions(+) create mode 100644 app/javascript/flavours/glitch/features/follow_recommendations/components/account.js create mode 100644 app/javascript/flavours/glitch/features/follow_recommendations/index.js (limited to 'app/javascript/flavours/glitch/features') diff --git a/app/javascript/flavours/glitch/features/follow_recommendations/components/account.js b/app/javascript/flavours/glitch/features/follow_recommendations/components/account.js new file mode 100644 index 000000000..bee9f9384 --- /dev/null +++ b/app/javascript/flavours/glitch/features/follow_recommendations/components/account.js @@ -0,0 +1,85 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import { connect } from 'react-redux'; +import { makeGetAccount } from 'flavours/glitch/selectors'; +import Avatar from 'flavours/glitch/components/avatar'; +import DisplayName from 'flavours/glitch/components/display_name'; +import Permalink from 'flavours/glitch/components/permalink'; +import IconButton from 'flavours/glitch/components/icon_button'; +import { injectIntl, defineMessages } from 'react-intl'; +import { followAccount, unfollowAccount } from 'flavours/glitch/actions/accounts'; + +const messages = defineMessages({ + follow: { id: 'account.follow', defaultMessage: 'Follow' }, + unfollow: { id: 'account.unfollow', defaultMessage: 'Unfollow' }, +}); + +const makeMapStateToProps = () => { + const getAccount = makeGetAccount(); + + const mapStateToProps = (state, props) => ({ + account: getAccount(state, props.id), + }); + + return mapStateToProps; +}; + +const getFirstSentence = str => { + const arr = str.split(/(([\.\?!]+\s)|[.。?!])/); + + return arr[0]; +}; + +export default @connect(makeMapStateToProps) +@injectIntl +class Account extends ImmutablePureComponent { + + static propTypes = { + account: ImmutablePropTypes.map.isRequired, + intl: PropTypes.object.isRequired, + dispatch: PropTypes.func.isRequired, + }; + + handleFollow = () => { + const { account, dispatch } = this.props; + + if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) { + dispatch(unfollowAccount(account.get('id'))); + } else { + dispatch(followAccount(account.get('id'))); + } + } + + render () { + const { account, intl } = this.props; + + let button; + + if (account.getIn(['relationship', 'following'])) { + button = ; + } else { + button = ; + } + + return ( +
+
+ +
+ + + +
{getFirstSentence(account.get('note_plain'))}
+
+ +
+ {button} +
+
+
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/follow_recommendations/index.js b/app/javascript/flavours/glitch/features/follow_recommendations/index.js new file mode 100644 index 000000000..ac75062e0 --- /dev/null +++ b/app/javascript/flavours/glitch/features/follow_recommendations/index.js @@ -0,0 +1,95 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import { connect } from 'react-redux'; +import { FormattedMessage } from 'react-intl'; +import { fetchSuggestions } from 'flavours/glitch/actions/suggestions'; +import { changeSetting, saveSettings } from 'flavours/glitch/actions/settings'; +import { requestBrowserPermission } from 'flavours/glitch/actions/notifications'; +import Column from 'flavours/glitch/features/ui/components/column'; +import Account from './components/account'; +import Logo from 'flavours/glitch/components/logo'; +import imageGreeting from 'mastodon/../images/elephant_ui_greeting.svg'; +import Button from 'flavours/glitch/components/button'; + +const mapStateToProps = state => ({ + suggestions: state.getIn(['suggestions', 'items']), + isLoading: state.getIn(['suggestions', 'isLoading']), +}); + +export default @connect(mapStateToProps) +class FollowRecommendations extends ImmutablePureComponent { + + static contextTypes = { + router: PropTypes.object.isRequired, + }; + + static propTypes = { + dispatch: PropTypes.func.isRequired, + suggestions: ImmutablePropTypes.list, + isLoading: PropTypes.bool, + }; + + componentDidMount () { + const { dispatch, suggestions } = this.props; + + // Don't re-fetch if we're e.g. navigating backwards to this page, + // since we don't want followed accounts to disappear from the list + + if (suggestions.size === 0) { + dispatch(fetchSuggestions(true)); + } + } + + handleDone = () => { + const { dispatch } = this.props; + const { router } = this.context; + + dispatch(requestBrowserPermission((permission) => { + if (permission === 'granted') { + dispatch(changeSetting(['notifications', 'alerts', 'follow'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'favourite'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'reblog'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'mention'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'poll'], true)); + dispatch(changeSetting(['notifications', 'alerts', 'status'], true)); + dispatch(saveSettings()); + } + })); + + router.history.push('/timelines/home'); + } + + render () { + const { suggestions, isLoading } = this.props; + + return ( + +
+
+ +

+

+
+ + {!isLoading && ( + +
+ {suggestions.map(suggestion => ( + + ))} +
+ +
+ + +
+
+ )} +
+
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js index 61a34fd2b..1149eb14e 100644 --- a/app/javascript/flavours/glitch/features/ui/index.js +++ b/app/javascript/flavours/glitch/features/ui/index.js @@ -50,9 +50,11 @@ import { Search, GettingStartedMisc, Directory, + FollowRecommendations, } from 'flavours/glitch/util/async-components'; import { HotKeys } from 'react-hotkeys'; import { me } from 'flavours/glitch/util/initial_state'; +import { closeOnboarding, INTRODUCTION_VERSION } from 'flavours/glitch/actions/onboarding'; import { defineMessages, FormattedMessage, injectIntl } from 'react-intl'; // Dummy import, to make sure that ends up in the application bundle. @@ -75,6 +77,7 @@ const mapStateToProps = state => ({ showFaviconBadge: state.getIn(['local_settings', 'notifications', 'favicon_badge']), hicolorPrivacyIcons: state.getIn(['local_settings', 'hicolor_privacy_icons']), moved: state.getIn(['accounts', me, 'moved']) && state.getIn(['accounts', state.getIn(['accounts', me, 'moved'])]), + firstLaunch: state.getIn(['settings', 'introductionVersion'], 0) < INTRODUCTION_VERSION, }); const keyMap = { @@ -207,6 +210,7 @@ class SwitchingColumnsArea extends React.PureComponent { + @@ -260,6 +264,7 @@ class UI extends React.Component { unreadNotifications: PropTypes.number, showFaviconBadge: PropTypes.bool, moved: PropTypes.map, + firstLaunch: PropTypes.bool, }; state = { @@ -378,6 +383,12 @@ class UI extends React.Component { this.favicon = new Favico({ animation:"none" }); + // On first launch, redirect to the follow recommendations page + if (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()); -- cgit