From 0ff1d62c7a5f6b62799a028364b819a5b0686af1 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 29 Sep 2022 04:39:33 +0200 Subject: [Glitch] Add logged-out access to the web UI Port part of 43b5d5e38d2b8ad8f1d1ad0911c3c1718159c912 to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/styles/components/columns.scss | 14 ++++++++++ .../flavours/glitch/styles/components/index.scss | 2 ++ .../glitch/styles/components/signed_out.scss | 8 ++++++ .../glitch/styles/components/single_column.scss | 32 +++++++++++++++++++--- 4 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 app/javascript/flavours/glitch/styles/components/signed_out.scss (limited to 'app/javascript/flavours/glitch/styles/components') 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; -- cgit From b38361a34748a49c9cd2e00adcd92a4609d27145 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 29 Sep 2022 06:21:51 +0200 Subject: [Glitch] Fix various issues with logged-out Web UI Port fixes from e623c302d5d4dfc05689eb8fb8e051e30fc38ec8 to glitch-soc Signed-off-by: Claire --- app/javascript/flavours/glitch/components/column_header.js | 3 ++- app/javascript/flavours/glitch/components/poll.js | 6 +++++- .../flavours/glitch/features/ui/components/link_footer.js | 6 ++++++ app/javascript/flavours/glitch/styles/components/columns.scss | 5 +++++ 4 files changed, 18 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/styles/components') diff --git a/app/javascript/flavours/glitch/components/column_header.js b/app/javascript/flavours/glitch/components/column_header.js index 500612093..024068c58 100644 --- a/app/javascript/flavours/glitch/components/column_header.js +++ b/app/javascript/flavours/glitch/components/column_header.js @@ -17,6 +17,7 @@ class ColumnHeader extends React.PureComponent { static contextTypes = { router: PropTypes.object, + identity: PropTypes.object, }; static propTypes = { @@ -150,7 +151,7 @@ class ColumnHeader extends React.PureComponent { collapsedContent.push(moveButtons); } - if (children || (multiColumn && this.props.onPin)) { + if (this.context.identity.signedIn && (children || (multiColumn && this.props.onPin))) { collapseButton = ( } + {!showResults && } {showResults && !this.props.disabled && · } {votesCount} {poll.get('expires_at') && · {timeRemaining}} 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 bb8f89e0f..6f4a8c2de 100644 --- a/app/javascript/flavours/glitch/features/ui/components/link_footer.js +++ b/app/javascript/flavours/glitch/features/ui/components/link_footer.js @@ -34,6 +34,7 @@ class LinkFooter extends React.PureComponent { }; static propTypes = { + withHotkeys: PropTypes.bool, onLogout: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, }; @@ -48,6 +49,7 @@ class LinkFooter extends React.PureComponent { } render () { + const { withHotkeys } = this.props; const { signedIn, permissions } = this.context.identity; const items = []; @@ -56,6 +58,10 @@ class LinkFooter extends React.PureComponent { items.push(); } + if (signedIn && withHotkeys) { + items.push(); + } + if (signedIn && securityLink) { items.push(); } diff --git a/app/javascript/flavours/glitch/styles/components/columns.scss b/app/javascript/flavours/glitch/styles/components/columns.scss index f5b712499..762e5dbb9 100644 --- a/app/javascript/flavours/glitch/styles/components/columns.scss +++ b/app/javascript/flavours/glitch/styles/components/columns.scss @@ -366,6 +366,11 @@ &:focus { text-shadow: 0 0 4px darken($ui-highlight-color, 5%); } + + &:disabled { + color: $dark-text-color; + cursor: default; + } } .column-header__notif-cleaning-buttons { -- cgit From 1ddd2186de5112c5c844d6ed64cf6d3730e2f3f6 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Thu, 29 Sep 2022 06:21:51 +0200 Subject: [Glitch] Add sign-up button to logged-out web UI Port e623c302d5d4dfc05689eb8fb8e051e30fc38ec8 to glitch-soc Signed-off-by: Claire --- .../glitch/features/ui/components/sign_in_banner.js | 2 ++ .../flavours/glitch/styles/components/index.scss | 20 ++++++++++++++++++++ .../glitch/styles/components/signed_out.scss | 4 ++++ app/javascript/flavours/glitch/util/initial_state.js | 1 + 4 files changed, 27 insertions(+) (limited to 'app/javascript/flavours/glitch/styles/components') 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 index c8403a8ad..e08a1ea67 100644 --- a/app/javascript/flavours/glitch/features/ui/components/sign_in_banner.js +++ b/app/javascript/flavours/glitch/features/ui/components/sign_in_banner.js @@ -1,10 +1,12 @@ import React from 'react'; import { FormattedMessage } from 'react-intl'; +import { registrationsOpen } from 'flavours/glitch/util/initial_state'; const SignInBanner = () => (

+
); diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss index cf5339d36..1c3540b33 100644 --- a/app/javascript/flavours/glitch/styles/components/index.scss +++ b/app/javascript/flavours/glitch/styles/components/index.scss @@ -118,6 +118,26 @@ } } + &.button-tertiary { + background: transparent; + padding: 6px 17px; + color: $highlight-text-color; + border: 1px solid $highlight-text-color; + + &:active, + &:focus, + &:hover { + background: $ui-highlight-color; + color: $primary-text-color; + border: 0; + padding: 7px 18px; + } + + &:disabled { + opacity: 0.5; + } + } + &.button--block { display: block; width: 100%; diff --git a/app/javascript/flavours/glitch/styles/components/signed_out.scss b/app/javascript/flavours/glitch/styles/components/signed_out.scss index 2b5cccd92..74eccf497 100644 --- a/app/javascript/flavours/glitch/styles/components/signed_out.scss +++ b/app/javascript/flavours/glitch/styles/components/signed_out.scss @@ -5,4 +5,8 @@ color: $darker-text-color; margin-bottom: 20px; } + + .button { + margin-bottom: 10px; + } } diff --git a/app/javascript/flavours/glitch/util/initial_state.js b/app/javascript/flavours/glitch/util/initial_state.js index af29e4735..4db3e6c64 100644 --- a/app/javascript/flavours/glitch/util/initial_state.js +++ b/app/javascript/flavours/glitch/util/initial_state.js @@ -25,6 +25,7 @@ export const searchEnabled = getMeta('search_enabled'); export const maxChars = (initialState && initialState.max_toot_chars) || 500; export const pollLimits = (initialState && initialState.poll_limits); export const limitedFederationMode = getMeta('limited_federation_mode'); +export const registrationsOpen = getMeta('registrations_open'); export const repository = getMeta('repository'); export const source_url = getMeta('source_url'); export const version = getMeta('version'); -- cgit From c9fadb3caede626a371cc481cbe1f2dba0bec0c4 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Fri, 7 Oct 2022 10:14:31 +0200 Subject: [Glitch] Add interaction modal to logged-out web UI Port 7fb738c8372a700e1b42534cb202005b8c73b946 to glitch-soc Signed-off-by: Claire --- .../flavours/glitch/components/status.js | 1 + .../glitch/components/status_action_bar.js | 29 +++-- .../flavours/glitch/containers/status_container.js | 8 ++ .../glitch/features/account/components/header.js | 3 +- .../features/account_timeline/components/header.js | 6 + .../containers/header_container.js | 8 ++ .../glitch/features/interaction_modal/index.js | 132 +++++++++++++++++++++ .../picture_in_picture/components/footer.js | 66 ++++++++--- .../features/status/components/action_bar.js | 5 +- .../flavours/glitch/features/status/index.js | 71 +++++++---- .../glitch/features/ui/components/modal_root.js | 2 + .../flavours/glitch/styles/components/modal.scss | 121 +++++++++++++++++++ 12 files changed, 397 insertions(+), 55 deletions(-) create mode 100644 app/javascript/flavours/glitch/features/interaction_modal/index.js (limited to 'app/javascript/flavours/glitch/styles/components') diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.js index d3b6bd7e9..9b656b2b3 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.js @@ -83,6 +83,7 @@ class Status extends ImmutablePureComponent { onEmbed: PropTypes.func, onHeightChange: PropTypes.func, onToggleHidden: PropTypes.func, + onInteractionModal: PropTypes.func, muted: PropTypes.bool, hidden: PropTypes.bool, unread: PropTypes.bool, diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.js index 78964e882..4e5e5121a 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.js @@ -69,6 +69,7 @@ class StatusActionBar extends ImmutablePureComponent { onBookmark: PropTypes.func, onFilter: PropTypes.func, onAddFilter: PropTypes.func, + onInteractionModal: PropTypes.func, withDismiss: PropTypes.bool, withCounters: PropTypes.bool, showReplyCount: PropTypes.bool, @@ -86,10 +87,12 @@ class StatusActionBar extends ImmutablePureComponent { ] handleReplyClick = () => { - if (me) { + const { signedIn } = this.context.identity; + + if (signedIn) { this.props.onReply(this.props.status, this.context.router.history); } else { - this._openInteractionDialog('reply'); + this.props.onInteractionModal('reply', this.props.status); } } @@ -101,28 +104,28 @@ class StatusActionBar extends ImmutablePureComponent { } handleFavouriteClick = (e) => { - if (me) { + const { signedIn } = this.context.identity; + + if (signedIn) { this.props.onFavourite(this.props.status, e); } else { - this._openInteractionDialog('favourite'); + this.props.onInteractionModal('favourite', this.props.status); } } - handleBookmarkClick = (e) => { - this.props.onBookmark(this.props.status, e); - } - handleReblogClick = e => { - if (me) { + const { signedIn } = this.context.identity; + + if (signedIn) { this.props.onReblog(this.props.status, e); } else { - this._openInteractionDialog('reblog'); + this.props.onInteractionModal('reblog', this.props.status); } } - _openInteractionDialog = type => { - window.open(`/interact/${this.props.status.get('id')}?type=${type}`, 'mastodon-intent', 'width=445,height=600,resizable=no,menubar=no,status=no,scrollbars=yes'); - } + handleBookmarkClick = (e) => { + this.props.onBookmark(this.props.status, e); + } handleDeleteClick = () => { this.props.onDelete(this.props.status, this.context.router.history); diff --git a/app/javascript/flavours/glitch/containers/status_container.js b/app/javascript/flavours/glitch/containers/status_container.js index 370308043..a1b4c57c6 100644 --- a/app/javascript/flavours/glitch/containers/status_container.js +++ b/app/javascript/flavours/glitch/containers/status_container.js @@ -244,6 +244,14 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({ }); }, + onInteractionModal (type, status) { + dispatch(openModal('INTERACTION', { + type, + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + })); + }, + }); export default injectIntl(connect(makeMapStateToProps, mapDispatchToProps)(Status)); diff --git a/app/javascript/flavours/glitch/features/account/components/header.js b/app/javascript/flavours/glitch/features/account/components/header.js index a6dc9d191..fc80446b1 100644 --- a/app/javascript/flavours/glitch/features/account/components/header.js +++ b/app/javascript/flavours/glitch/features/account/components/header.js @@ -96,6 +96,7 @@ class Header extends ImmutablePureComponent { onAddToList: PropTypes.func.isRequired, onEditAccountNote: PropTypes.func.isRequired, onChangeLanguages: PropTypes.func.isRequired, + onInteractionModal: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, domain: PropTypes.string.isRequired, hidden: PropTypes.bool, @@ -172,7 +173,7 @@ class Header extends ImmutablePureComponent { } else if (account.getIn(['relationship', 'requested'])) { actionBtn = + + ); + } + +} + +export default @connect(mapStateToProps) +class InteractionModal extends React.PureComponent { + + static propTypes = { + displayNameHtml: PropTypes.string, + url: PropTypes.string, + type: PropTypes.oneOf(['reply', 'reblog', 'favourite', 'follow']), + }; + + render () { + const { url, type, displayNameHtml } = this.props; + + const name = ; + + let title, actionDescription, icon; + + switch(type) { + case 'reply': + icon = ; + title = ; + actionDescription = ; + break; + case 'reblog': + icon = ; + title = ; + actionDescription = ; + break; + case 'favourite': + icon = ; + title = ; + actionDescription = ; + break; + case 'follow': + icon = ; + title = ; + actionDescription = ; + break; + } + + return ( +
+
+

{icon} {title}

+

{actionDescription}

+
+ +
+
+

+ + +
+ +
+

+

+ +
+
+
+ ); + } + +} diff --git a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.js b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.js index 0408105ae..2a5adf71d 100644 --- a/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.js +++ b/app/javascript/flavours/glitch/features/picture_in_picture/components/footer.js @@ -44,6 +44,7 @@ class Footer extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object, + identity: PropTypes.object, }; static propTypes = { @@ -69,26 +70,44 @@ class Footer extends ImmutablePureComponent { }; handleReplyClick = () => { - const { dispatch, askReplyConfirmation, intl } = this.props; - - if (askReplyConfirmation) { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.replyMessage), - confirm: intl.formatMessage(messages.replyConfirm), - onConfirm: this._performReply, - })); + const { dispatch, askReplyConfirmation, status, intl } = this.props; + const { signedIn } = this.context.identity; + + if (signedIn) { + if (askReplyConfirmation) { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onConfirm: this._performReply, + })); + } else { + this._performReply(); + } } else { - this._performReply(); + dispatch(openModal('INTERACTION', { + type: 'reply', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + })); } }; handleFavouriteClick = () => { const { dispatch, status } = this.props; - - if (status.get('favourited')) { - dispatch(unfavourite(status)); + const { signedIn } = this.context.identity; + + if (signedIn) { + if (status.get('favourited')) { + dispatch(unfavourite(status)); + } else { + dispatch(favourite(status)); + } } else { - dispatch(favourite(status)); + dispatch(openModal('INTERACTION', { + type: 'favourite', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + })); } }; @@ -99,13 +118,22 @@ class Footer extends ImmutablePureComponent { handleReblogClick = e => { const { dispatch, status } = this.props; - - if (status.get('reblogged')) { - dispatch(unreblog(status)); - } else if ((e && e.shiftKey) || !boostModal) { - this._performReblog(); + const { signedIn } = this.context.identity; + + if (signedIn) { + if (status.get('reblogged')) { + dispatch(unreblog(status)); + } else if ((e && e.shiftKey) || !boostModal) { + this._performReblog(); + } else { + dispatch(initBoostModal({ status, onReblog: this._performReblog })); + } } else { - dispatch(initBoostModal({ status, onReblog: this._performReblog })); + dispatch(openModal('INTERACTION', { + type: 'reblog', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + })); } }; diff --git a/app/javascript/flavours/glitch/features/status/components/action_bar.js b/app/javascript/flavours/glitch/features/status/components/action_bar.js index ef0f0f2b7..75ad462f0 100644 --- a/app/javascript/flavours/glitch/features/status/components/action_bar.js +++ b/app/javascript/flavours/glitch/features/status/components/action_bar.js @@ -152,6 +152,7 @@ class ActionBar extends React.PureComponent { render () { const { status, intl } = this.props; + const { signedIn, permissions } = this.context.identity; const publicStatus = ['public', 'unlisted'].includes(status.get('visibility')); const pinnableStatus = ['public', 'unlisted', 'private'].includes(status.get('visibility')); @@ -184,7 +185,7 @@ class ActionBar extends React.PureComponent { menu.push({ text: intl.formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick }); menu.push({ text: intl.formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); menu.push({ text: intl.formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); - if ((this.context.identity.permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS && (accountAdminLink || statusAdminLink)) { + if ((permissions & PERMISSION_MANAGE_USERS) === PERMISSION_MANAGE_USERS && (accountAdminLink || statusAdminLink)) { menu.push(null); if (accountAdminLink !== undefined) { menu.push({ @@ -224,7 +225,7 @@ class ActionBar extends React.PureComponent {
{shareButton} -
+
diff --git a/app/javascript/flavours/glitch/features/status/index.js b/app/javascript/flavours/glitch/features/status/index.js index 36f79bb0c..8e783af80 100644 --- a/app/javascript/flavours/glitch/features/status/index.js +++ b/app/javascript/flavours/glitch/features/status/index.js @@ -171,6 +171,7 @@ class Status extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object, + identity: PropTypes.object, }; static propTypes = { @@ -263,14 +264,25 @@ class Status extends ImmutablePureComponent { } handleFavouriteClick = (status, e) => { - if (status.get('favourited')) { - this.props.dispatch(unfavourite(status)); - } else { - if ((e && e.shiftKey) || !favouriteModal) { - this.handleModalFavourite(status); + const { dispatch } = this.props; + const { signedIn } = this.context.identity; + + if (signedIn) { + if (status.get('favourited')) { + dispatch(unfavourite(status)); } else { - this.props.dispatch(openModal('FAVOURITE', { status, onFavourite: this.handleModalFavourite })); + if ((e && e.shiftKey) || !favouriteModal) { + this.handleModalFavourite(status); + } else { + dispatch(openModal('FAVOURITE', { status, onFavourite: this.handleModalFavourite })); + } } + } else { + dispatch(openModal('INTERACTION', { + type: 'favourite', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + })); } } @@ -283,16 +295,26 @@ class Status extends ImmutablePureComponent { } handleReplyClick = (status) => { - let { askReplyConfirmation, dispatch, intl } = this.props; - if (askReplyConfirmation) { - dispatch(openModal('CONFIRM', { - message: intl.formatMessage(messages.replyMessage), - confirm: intl.formatMessage(messages.replyConfirm), - onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)), - onConfirm: () => dispatch(replyCompose(status, this.context.router.history)), - })); + const { askReplyConfirmation, dispatch, intl } = this.props; + const { signedIn } = this.context.identity; + + if (signedIn) { + if (askReplyConfirmation) { + dispatch(openModal('CONFIRM', { + message: intl.formatMessage(messages.replyMessage), + confirm: intl.formatMessage(messages.replyConfirm), + onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_before_clearing_draft'], false)), + onConfirm: () => dispatch(replyCompose(status, this.context.router.history)), + })); + } else { + dispatch(replyCompose(status, this.context.router.history)); + } } else { - dispatch(replyCompose(status, this.context.router.history)); + dispatch(openModal('INTERACTION', { + type: 'reply', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + })); } } @@ -308,13 +330,22 @@ class Status extends ImmutablePureComponent { handleReblogClick = (status, e) => { const { settings, dispatch } = this.props; + const { signedIn } = this.context.identity; - if (settings.get('confirm_boost_missing_media_description') && status.get('media_attachments').some(item => !item.get('description')) && !status.get('reblogged')) { - dispatch(initBoostModal({ status, onReblog: this.handleModalReblog, missingMediaDescription: true })); - } else if ((e && e.shiftKey) || !boostModal) { - this.handleModalReblog(status); + if (signedIn) { + if (settings.get('confirm_boost_missing_media_description') && status.get('media_attachments').some(item => !item.get('description')) && !status.get('reblogged')) { + dispatch(initBoostModal({ status, onReblog: this.handleModalReblog, missingMediaDescription: true })); + } else if ((e && e.shiftKey) || !boostModal) { + this.handleModalReblog(status); + } else { + dispatch(initBoostModal({ status, onReblog: this.handleModalReblog })); + } } else { - dispatch(initBoostModal({ status, onReblog: this.handleModalReblog })); + dispatch(openModal('INTERACTION', { + type: 'reblog', + accountId: status.getIn(['account', 'id']), + url: status.get('url'), + })); } } diff --git a/app/javascript/flavours/glitch/features/ui/components/modal_root.js b/app/javascript/flavours/glitch/features/ui/components/modal_root.js index 7e8082f99..92768caeb 100644 --- a/app/javascript/flavours/glitch/features/ui/components/modal_root.js +++ b/app/javascript/flavours/glitch/features/ui/components/modal_root.js @@ -16,6 +16,7 @@ import ConfirmationModal from './confirmation_modal'; import SubscribedLanguagesModal from 'flavours/glitch/features/subscribed_languages_modal'; import FocalPointModal from './focal_point_modal'; import DeprecatedSettingsModal from './deprecated_settings_modal'; +import InteractionModal from 'flavours/glitch/features/interaction_modal'; import { OnboardingModal, MuteModal, @@ -53,6 +54,7 @@ const MODAL_COMPONENTS = { 'COMPARE_HISTORY': CompareHistoryModal, 'FILTER': FilterModal, 'SUBSCRIBED_LANGUAGES': () => Promise.resolve({ default: SubscribedLanguagesModal }), + 'INTERACTION': () => Promise.resolve({ default: InteractionModal }), }; export default class ModalRoot extends React.PureComponent { diff --git a/app/javascript/flavours/glitch/styles/components/modal.scss b/app/javascript/flavours/glitch/styles/components/modal.scss index e95bea0d7..cd96f83d6 100644 --- a/app/javascript/flavours/glitch/styles/components/modal.scss +++ b/app/javascript/flavours/glitch/styles/components/modal.scss @@ -23,6 +23,7 @@ left: 0; width: 100%; height: 100%; + box-sizing: border-box; display: flex; flex-direction: column; align-items: center; @@ -1304,3 +1305,123 @@ img.modal-warning { margin-bottom: 15px; width: 60px; } + +.interaction-modal { + max-width: 90vw; + width: 600px; + background: $ui-base-color; + border-radius: 8px; + overflow: hidden; + position: relative; + display: block; + padding: 20px; + + h3 { + font-size: 22px; + line-height: 33px; + font-weight: 700; + text-align: center; + } + + &__icon { + color: $highlight-text-color; + margin: 0 5px; + } + + &__lead { + padding: 20px; + text-align: center; + + h3 { + margin-bottom: 15px; + } + + p { + font-size: 17px; + line-height: 22px; + color: $darker-text-color; + } + } + + &__choices { + display: flex; + + &__choice { + flex: 0 0 auto; + width: 50%; + box-sizing: border-box; + padding: 20px; + + h3 { + margin-bottom: 20px; + } + + p { + color: $darker-text-color; + margin-bottom: 20px; + } + + .button { + margin-bottom: 10px; + + &:last-child { + margin-bottom: 0; + } + } + } + } + + @media screen and (max-width: $no-gap-breakpoint - 1px) { + &__choices { + display: block; + + &__choice { + width: auto; + margin-bottom: 20px; + } + } + } +} + +.copypaste { + display: flex; + align-items: center; + gap: 10px; + + input { + display: block; + font-family: inherit; + background: darken($ui-base-color, 8%); + border: 1px solid $highlight-text-color; + color: $darker-text-color; + border-radius: 4px; + padding: 6px 9px; + line-height: 22px; + font-size: 14px; + transition: border-color 300ms linear; + flex: 1 1 auto; + overflow: hidden; + + &:focus { + outline: 0; + background: darken($ui-base-color, 4%); + } + } + + .button { + flex: 0 0 auto; + transition: background 300ms linear; + } + + &.copied { + input { + border: 1px solid $valid-value-color; + transition: none; + } + + .button { + background: $valid-value-color; + transition: none; + } + } +} -- cgit From 757e16a0b553508213c8707f4b6f210273dde964 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 5 Oct 2022 03:47:56 +0200 Subject: [Glitch] Add server banner to web app Port d2528b26b6da34f34b5d7a392e263428d3c09d69 to glitch-soc Signed-off-by: Claire --- app/javascript/flavours/glitch/actions/rules.js | 27 ------- app/javascript/flavours/glitch/actions/server.js | 30 +++++++ .../flavours/glitch/components/account.js | 14 +++- .../flavours/glitch/components/display_name.js | 17 ++-- .../flavours/glitch/components/server_banner.js | 91 ++++++++++++++++++++++ .../flavours/glitch/features/report/rules.js | 2 +- .../glitch/features/ui/components/compose_panel.js | 2 + .../glitch/features/ui/components/report_modal.js | 4 +- .../flavours/glitch/features/ui/index.js | 4 +- app/javascript/flavours/glitch/reducers/index.js | 4 +- app/javascript/flavours/glitch/reducers/rules.js | 13 ---- app/javascript/flavours/glitch/reducers/server.js | 19 +++++ .../glitch/styles/components/signed_out.scss | 82 +++++++++++++++++++ .../flavours/glitch/util/initial_state.js | 1 - 14 files changed, 254 insertions(+), 56 deletions(-) delete mode 100644 app/javascript/flavours/glitch/actions/rules.js create mode 100644 app/javascript/flavours/glitch/actions/server.js create mode 100644 app/javascript/flavours/glitch/components/server_banner.js delete mode 100644 app/javascript/flavours/glitch/reducers/rules.js create mode 100644 app/javascript/flavours/glitch/reducers/server.js (limited to 'app/javascript/flavours/glitch/styles/components') 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 ( +
+
+ {domain}, mastodon: Mastodon }} /> +
+ + {server.get('title')} + +
+ {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; -- cgit From d04fbe6fe06113041662bbd9816198256d3cd385 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Wed, 5 Oct 2022 07:02:09 +0200 Subject: [Glitch] Change font size of active users in server banner to be larger in web UI Port 0e41d360c068deb8655dc1b9facfa4c15985c271 to glitch-soc Signed-off-by: Claire --- app/javascript/flavours/glitch/styles/components/signed_out.scss | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/javascript/flavours/glitch/styles/components') diff --git a/app/javascript/flavours/glitch/styles/components/signed_out.scss b/app/javascript/flavours/glitch/styles/components/signed_out.scss index a318bf66b..1051b2f32 100644 --- a/app/javascript/flavours/glitch/styles/components/signed_out.scss +++ b/app/javascript/flavours/glitch/styles/components/signed_out.scss @@ -65,11 +65,13 @@ &__number { font-weight: 600; color: $primary-text-color; + font-size: 14px; } &__number-label { color: $darker-text-color; font-weight: 500; + font-size: 14px; } h4 { -- cgit