diff --git a/app/javascript/flavours/glitch/components/account.jsx b/app/javascript/flavours/glitch/components/account.jsx
index 109e0daddd50d8..4d592b6133c455 100644
--- a/app/javascript/flavours/glitch/components/account.jsx
+++ b/app/javascript/flavours/glitch/components/account.jsx
@@ -44,6 +44,8 @@ class Account extends ImmutablePureComponent {
intl: PropTypes.object.isRequired,
hidden: PropTypes.bool,
minimal: PropTypes.bool,
+ actionIcon: PropTypes.string,
+ actionTitle: PropTypes.string,
defaultAction: PropTypes.string,
withBio: PropTypes.bool,
};
diff --git a/app/javascript/flavours/glitch/features/compose/components/reply_indicator.jsx b/app/javascript/flavours/glitch/features/compose/components/reply_indicator.jsx
index 661dff3d54dbd5..6a8bf6e882047c 100644
--- a/app/javascript/flavours/glitch/features/compose/components/reply_indicator.jsx
+++ b/app/javascript/flavours/glitch/features/compose/components/reply_indicator.jsx
@@ -6,9 +6,11 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import AttachmentList from 'flavours/glitch/components/attachment_list';
+import { WithOptionalRouterPropTypes, withOptionalRouter } from 'flavours/glitch/utils/react_router';
+import { Avatar } from '../../../components/avatar';
+import { DisplayName } from '../../../components/display_name';
import { IconButton } from '../../../components/icon_button';
-import AccountContainer from '../../../containers/account_container';
const messages = defineMessages({
cancel: { id: 'reply_indicator.cancel', defaultMessage: 'Cancel' },
@@ -18,14 +20,19 @@ class ReplyIndicator extends ImmutablePureComponent {
static propTypes = {
status: ImmutablePropTypes.map,
- onCancel: PropTypes.func,
+ onCancel: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
+ ...WithOptionalRouterPropTypes,
};
handleClick = () => {
- const { onCancel } = this.props;
- if (onCancel) {
- onCancel();
+ this.props.onCancel();
+ };
+
+ handleAccountClick = (e) => {
+ if (e.button === 0 && !(e.ctrlKey || e.metaKey)) {
+ e.preventDefault();
+ this.props.history?.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
}
};
@@ -38,19 +45,15 @@ class ReplyIndicator extends ImmutablePureComponent {
const content = { __html: status.get('contentHtml') };
- const account = status.get('account');
-
return (
- {account && (
-
- )}
+
+
+
+
@@ -67,4 +70,4 @@ class ReplyIndicator extends ImmutablePureComponent {
}
-export default injectIntl(ReplyIndicator);
+export default withOptionalRouter(injectIntl(ReplyIndicator));
diff --git a/app/javascript/flavours/glitch/features/compose/containers/reply_indicator_container.js b/app/javascript/flavours/glitch/features/compose/containers/reply_indicator_container.js
index 678124b2a8d93c..1147e448afef33 100644
--- a/app/javascript/flavours/glitch/features/compose/containers/reply_indicator_container.js
+++ b/app/javascript/flavours/glitch/features/compose/containers/reply_indicator_container.js
@@ -1,9 +1,12 @@
import { connect } from 'react-redux';
import { cancelReplyCompose } from '../../../actions/compose';
+import { makeGetStatus } from '../../../selectors';
import ReplyIndicator from '../components/reply_indicator';
const makeMapStateToProps = () => {
+ const getStatus = makeGetStatus();
+
const mapStateToProps = state => {
let statusId = state.getIn(['compose', 'id'], null);
let editing = true;
@@ -14,7 +17,7 @@ const makeMapStateToProps = () => {
}
return {
- status: state.getIn(['statuses', statusId]),
+ status: getStatus(state, { id: statusId }),
editing,
};
};
diff --git a/app/javascript/flavours/glitch/styles/components/compose_form.scss b/app/javascript/flavours/glitch/styles/components/compose_form.scss
index 0f64c0dcc10f5a..d84e672b8f0d08 100644
--- a/app/javascript/flavours/glitch/styles/components/compose_form.scss
+++ b/app/javascript/flavours/glitch/styles/components/compose_form.scss
@@ -141,10 +141,6 @@
.reply-indicator__header {
margin-bottom: 5px;
overflow: hidden;
-
- & > .account.small {
- color: $inverted-text-color;
- }
}
.reply-indicator__cancel {
@@ -152,6 +148,25 @@
line-height: 24px;
}
+.reply-indicator__display-name {
+ color: $inverted-text-color;
+ display: block;
+ max-width: 100%;
+ line-height: 24px;
+ overflow: hidden;
+ text-decoration: none;
+
+ & > .display-name {
+ line-height: unset;
+ height: unset;
+ }
+}
+
+.reply-indicator__display-avatar {
+ float: left;
+ margin-inline-end: 5px;
+}
+
.reply-indicator__content {
position: relative;
font-size: 14px;
diff --git a/app/javascript/packs/public.jsx b/app/javascript/packs/public.jsx
index 62ab7b42821a5f..3831137762f794 100644
--- a/app/javascript/packs/public.jsx
+++ b/app/javascript/packs/public.jsx
@@ -5,7 +5,7 @@ import { createRoot } from 'react-dom/client';
import { IntlMessageFormat } from 'intl-messageformat';
import { defineMessages } from 'react-intl';
-import delegate from '@rails/ujs';
+import Rails from '@rails/ujs';
import axios from 'axios';
import { throttle } from 'lodash';
@@ -129,7 +129,7 @@ function loaded() {
});
}
- delegate(document, '#user_account_attributes_username', 'input', throttle(({ target }) => {
+ Rails.delegate(document, '#user_account_attributes_username', 'input', throttle(({ target }) => {
if (target.value && target.value.length > 0) {
axios.get('/api/v1/accounts/lookup', { params: { acct: target.value } }).then(() => {
target.setCustomValidity(formatMessage(messages.usernameTaken));
@@ -141,7 +141,7 @@ function loaded() {
}
}, 500, { leading: false, trailing: true }));
- delegate(document, '#user_password,#user_password_confirmation', 'input', () => {
+ Rails.delegate(document, '#user_password,#user_password_confirmation', 'input', () => {
const password = document.getElementById('user_password');
const confirmation = document.getElementById('user_password_confirmation');
if (!confirmation) return;
@@ -155,7 +155,7 @@ function loaded() {
}
});
- delegate(document, '.status__content__spoiler-link', 'click', function() {
+ Rails.delegate(document, '.status__content__spoiler-link', 'click', function() {
const statusEl = this.parentNode.parentNode;
if (statusEl.dataset.spoiler === 'expanded') {
@@ -192,23 +192,23 @@ const toggleSidebar = () => {
sidebar.classList.toggle('visible');
};
-delegate(document, '.sidebar__toggle__icon', 'click', () => {
+Rails.delegate(document, '.sidebar__toggle__icon', 'click', () => {
toggleSidebar();
});
-delegate(document, '.sidebar__toggle__icon', 'keydown', e => {
+Rails.delegate(document, '.sidebar__toggle__icon', 'keydown', e => {
if (e.key === ' ' || e.key === 'Enter') {
e.preventDefault();
toggleSidebar();
}
});
-delegate(document, '.custom-emoji', 'mouseover', ({ target }) => target.src = target.getAttribute('data-original'));
-delegate(document, '.custom-emoji', 'mouseout', ({ target }) => target.src = target.getAttribute('data-static'));
+Rails.delegate(document, '.custom-emoji', 'mouseover', ({ target }) => target.src = target.getAttribute('data-original'));
+Rails.delegate(document, '.custom-emoji', 'mouseout', ({ target }) => target.src = target.getAttribute('data-static'));
// Empty the honeypot fields in JS in case something like an extension
// automatically filled them.
-delegate(document, '#registration_new_user,#new_user', 'submit', () => {
+Rails.delegate(document, '#registration_new_user,#new_user', 'submit', () => {
['user_website', 'user_confirm_password', 'registration_user_website', 'registration_user_confirm_password'].forEach(id => {
const field = document.getElementById(id);
if (field) {
diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb
index a8b61e356f01ab..b361c57133377d 100644
--- a/config/initializers/content_security_policy.rb
+++ b/config/initializers/content_security_policy.rb
@@ -12,6 +12,17 @@
assets_host = policy.assets_host
media_hosts = policy.media_hosts
+base_host = Rails.configuration.x.web_domain
+
+assets_host = Rails.configuration.action_controller.asset_host
+assets_host ||= host_to_url(base_host)
+
+media_host = host_to_url(ENV['S3_ALIAS_HOST'])
+media_host ||= host_to_url(ENV['S3_CLOUDFRONT_HOST'])
+media_host ||= host_to_url(ENV['AZURE_ALIAS_HOST'])
+media_host ||= host_to_url(ENV['S3_HOSTNAME']) if ENV['S3_ENABLED'] == 'true'
+media_host ||= assets_host
+
def sso_host
return unless ENV['ONE_CLICK_SSO_LOGIN'] == 'true'
return unless ENV['OMNIAUTH_ONLY'] == 'true'
diff --git a/spec/requests/content_security_policy_spec.rb b/spec/requests/content_security_policy_spec.rb
index d4cc40bce5d976..6d21c7ca275d8b 100644
--- a/spec/requests/content_security_policy_spec.rb
+++ b/spec/requests/content_security_policy_spec.rb
@@ -12,9 +12,9 @@
"default-src 'none'",
"frame-ancestors 'none'",
"font-src 'self' https://cb6e6126.ngrok.io",
- "img-src 'self' data: blob: https://cb6e6126.ngrok.io",
+ "img-src 'self' data: blob: https://cb6e6126.ngrok.io https://cb6e6126.ngrok.io",
"style-src 'self' https://cb6e6126.ngrok.io 'nonce-ZbA+JmE7+bK8F5qvADZHuQ=='",
- "media-src 'self' data: https://cb6e6126.ngrok.io",
+ "media-src 'self' data: https://cb6e6126.ngrok.io https://cb6e6126.ngrok.io",
"frame-src 'self' https:",
"manifest-src 'self' https://cb6e6126.ngrok.io",
"form-action 'self'",