Skip to content

Commit

Permalink
Merge pull request #2962 from ClearlyClaire/glitch-soc/merge-upstream
Browse files Browse the repository at this point in the history
Merge upstream changes up to f79b96a
  • Loading branch information
ClearlyClaire authored Feb 2, 2025
2 parents 65caf6c + a3399ed commit 29e0edb
Show file tree
Hide file tree
Showing 107 changed files with 969 additions and 410 deletions.
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
# See: https://docs.docker.com/build/building/multi-platform/
ARG TARGETPLATFORM=${TARGETPLATFORM}
ARG BUILDPLATFORM=${BUILDPLATFORM}
ARG BASE_REGISTRY="docker.io"

# Ruby image to use for base image, change with [--build-arg RUBY_VERSION="3.4.x"]
# renovate: datasource=docker depName=docker.io/ruby
Expand All @@ -19,9 +20,9 @@ ARG NODE_MAJOR_VERSION="22"
# Debian image to use for base image, change with [--build-arg DEBIAN_VERSION="bookworm"]
ARG DEBIAN_VERSION="bookworm"
# Node image to use for base image based on combined variables (ex: 20-bookworm-slim)
FROM docker.io/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
FROM ${BASE_REGISTRY}/node:${NODE_MAJOR_VERSION}-${DEBIAN_VERSION}-slim AS node
# Ruby image to use for base image based on combined variables (ex: 3.4.x-slim-bookworm)
FROM docker.io/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby
FROM ${BASE_REGISTRY}/ruby:${RUBY_VERSION}-slim-${DEBIAN_VERSION} AS ruby

# Resulting version string is vX.X.X-MASTODON_VERSION_PRERELEASE+MASTODON_VERSION_METADATA
# Example: v4.3.0-nightly.2023.11.09+pr-123456
Expand Down
10 changes: 5 additions & 5 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,7 @@ GEM
activesupport (>= 5.1)
haml (>= 4.0.6)
railties (>= 5.1)
haml_lint (0.59.0)
haml_lint (0.60.0)
haml (>= 5.0)
parallel (~> 1.10)
rainbow
Expand Down Expand Up @@ -591,7 +591,7 @@ GEM
date
stringio
public_suffix (6.0.1)
puma (6.5.0)
puma (6.6.0)
nio4r (~> 2.0)
pundit (2.4.0)
activesupport (>= 3.0.0)
Expand Down Expand Up @@ -716,14 +716,14 @@ GEM
rspec-mocks (~> 3.0)
sidekiq (>= 5, < 8)
rspec-support (3.13.2)
rubocop (1.71.0)
rubocop (1.71.1)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.36.2, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.38.0)
Expand Down Expand Up @@ -818,7 +818,7 @@ GEM
climate_control
test-prof (1.4.4)
thor (1.3.2)
tilt (2.5.0)
tilt (2.6.0)
timeout (0.4.3)
tpm-key_attestation (0.12.1)
bindata (~> 2.4)
Expand Down
3 changes: 3 additions & 0 deletions app/javascript/flavours/glitch/actions/compose.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@ export function directCompose(account) {
};
}

/**
* @param {null | string} overridePrivacy
*/
export function submitCompose(overridePrivacy = null) {
return function (dispatch, getState) {
let status = getState().getIn(['compose', 'text'], '');
Expand Down
16 changes: 13 additions & 3 deletions app/javascript/flavours/glitch/components/alt_text_badge.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useCallback, useRef } from 'react';
import { useState, useCallback, useRef, useId } from 'react';

import { FormattedMessage } from 'react-intl';

Expand All @@ -8,12 +8,15 @@ import type {
UsePopperOptions,
} from 'react-overlays/esm/usePopper';

import { useSelectableClick } from '@/hooks/useSelectableClick';

const offset = [0, 4] as OffsetValue;
const popperConfig = { strategy: 'fixed' } as UsePopperOptions;

export const AltTextBadge: React.FC<{
description: string;
}> = ({ description }) => {
const accessibilityId = useId();
const anchorRef = useRef<HTMLButtonElement>(null);
const [open, setOpen] = useState(false);

Expand All @@ -25,12 +28,16 @@ export const AltTextBadge: React.FC<{
setOpen(false);
}, [setOpen]);

const [handleMouseDown, handleMouseUp] = useSelectableClick(handleClose);

return (
<>
<button
ref={anchorRef}
className='media-gallery__alt__label'
onClick={handleClick}
aria-expanded={open}
aria-controls={accessibilityId}
>
ALT
</button>
Expand All @@ -47,9 +54,12 @@ export const AltTextBadge: React.FC<{
>
{({ props }) => (
<div {...props} className='hover-card-controller'>
<div
<div // eslint-disable-line jsx-a11y/no-noninteractive-element-interactions
className='media-gallery__alt__popover dropdown-animation'
role='tooltip'
role='region'
id={accessibilityId}
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp}
>
<h4>
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState, useRef, useCallback } from 'react';
import { useState, useRef, useCallback, useId } from 'react';

import { FormattedMessage } from 'react-intl';

Expand All @@ -16,6 +16,7 @@ export const DomainPill: React.FC<{
username: string;
isSelf: boolean;
}> = ({ domain, username, isSelf }) => {
const accessibilityId = useId();
const [open, setOpen] = useState(false);
const [expanded, setExpanded] = useState(false);
const triggerRef = useRef(null);
Expand All @@ -34,6 +35,8 @@ export const DomainPill: React.FC<{
className={classNames('account__domain-pill', { active: open })}
ref={triggerRef}
onClick={handleClick}
aria-expanded={open}
aria-controls={accessibilityId}
>
{domain}
</button>
Expand All @@ -48,6 +51,8 @@ export const DomainPill: React.FC<{
{({ props }) => (
<div
{...props}
role='region'
id={accessibilityId}
className='account__domain-pill__popout dropdown-animation'
>
<div className='account__domain-pill__popout__header'>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import classNames from 'classnames';

import Overlay from 'react-overlays/Overlay';

import { useSelectableClick } from '@/hooks/useSelectableClick';
import QuestionMarkIcon from '@/material-icons/400-24px/question_mark.svg?react';
import { Icon } from 'flavours/glitch/components/icon';

Expand All @@ -23,6 +24,8 @@ export const InfoButton: React.FC = () => {
setOpen(!open);
}, [open, setOpen]);

const [handleMouseDown, handleMouseUp] = useSelectableClick(handleClick);

return (
<>
<button
Expand All @@ -46,10 +49,13 @@ export const InfoButton: React.FC = () => {
target={triggerRef}
>
{({ props }) => (
<div
<div // eslint-disable-line jsx-a11y/no-noninteractive-element-interactions
{...props}
className='dialog-modal__popout prose dropdown-animation'
role='region'
id={accessibilityId}
onMouseDown={handleMouseDown}
onMouseUp={handleMouseUp}
>
<FormattedMessage
id='info_button.what_is_alt_text'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import ImmutablePureComponent from 'react-immutable-pure-component';

import { length } from 'stringz';

import { missingAltTextModal } from 'flavours/glitch/initial_state';

import AutosuggestInput from '../../../components/autosuggest_input';
import AutosuggestTextarea from '../../../components/autosuggest_textarea';
import { Button } from '../../../components/button';
Expand Down Expand Up @@ -72,9 +74,8 @@ class ComposeForm extends ImmutablePureComponent {
autoFocus: PropTypes.bool,
withoutNavigation: PropTypes.bool,
anyMedia: PropTypes.bool,
missingAltText: PropTypes.bool,
media: ImmutablePropTypes.list,
mediaDescriptionConfirmation: PropTypes.bool,
onMediaDescriptionConfirm: PropTypes.func.isRequired,
isInReply: PropTypes.bool,
singleColumn: PropTypes.bool,
lang: PropTypes.string,
Expand Down Expand Up @@ -131,17 +132,11 @@ class ComposeForm extends ImmutablePureComponent {
return;
}

this.props.onSubmit(missingAltTextModal && this.props.missingAltText, overridePrivacy);

if (e) {
e.preventDefault();
}

// Submit unless there are media with missing descriptions
if (this.props.mediaDescriptionConfirmation && this.props.media && this.props.media.some(item => !item.get('description'))) {
const firstWithoutDescription = this.props.media.find(item => !item.get('description'));
this.props.onMediaDescriptionConfirm(firstWithoutDescription.get('id'), overridePrivacy);
} else {
this.props.onSubmit(overridePrivacy);
}
};

handleSecondarySubmit = (e) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { defineMessages, injectIntl } from 'react-intl';
import { injectIntl } from 'react-intl';

import { connect } from 'react-redux';

import { privacyPreference } from 'flavours/glitch/utils/privacy_preference';

import {
changeCompose,
submitCompose,
Expand All @@ -13,27 +11,11 @@ import {
changeComposeSpoilerText,
insertEmojiCompose,
uploadCompose,
} from '../../../actions/compose';
import { changeLocalSetting } from '../../../actions/local_settings';
import {
openModal,
} from '../../../actions/modal';
import ComposeForm from '../components/compose_form';
} from 'flavours/glitch/actions/compose';
import { openModal } from 'flavours/glitch/actions/modal';
import { privacyPreference } from 'flavours/glitch/utils/privacy_preference';

const messages = defineMessages({
missingDescriptionMessage: {
id: 'confirmations.missing_media_description.message',
defaultMessage: 'At least one media attachment is lacking a description. Consider describing all media attachments for the visually impaired before sending your toot.',
},
missingDescriptionConfirm: {
id: 'confirmations.missing_media_description.confirm',
defaultMessage: 'Send anyway',
},
missingDescriptionEdit: {
id: 'confirmations.missing_media_description.edit',
defaultMessage: 'Edit media',
},
});
import ComposeForm from '../components/compose_form';

const sideArmPrivacy = state => {
const inReplyTo = state.getIn(['compose', 'in_reply_to']);
Expand Down Expand Up @@ -68,22 +50,29 @@ const mapStateToProps = state => ({
isChangingUpload: state.getIn(['compose', 'is_changing_upload']),
isUploading: state.getIn(['compose', 'is_uploading']),
anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
missingAltText: state.getIn(['compose', 'media_attachments']).some(media => ['image', 'gifv'].includes(media.get('type')) && (media.get('description') ?? '').length === 0),
isInReply: state.getIn(['compose', 'in_reply_to']) !== null,
lang: state.getIn(['compose', 'language']),
sideArm: sideArmPrivacy(state),
media: state.getIn(['compose', 'media_attachments']),
mediaDescriptionConfirmation: state.getIn(['local_settings', 'confirm_missing_media_description']),
maxChars: state.getIn(['server', 'server', 'configuration', 'statuses', 'max_characters'], 500),
});

const mapDispatchToProps = (dispatch, { intl }) => ({
const mapDispatchToProps = (dispatch) => ({

onChange (text) {
dispatch(changeCompose(text));
},

onSubmit (overridePrivacy = null) {
dispatch(submitCompose(overridePrivacy));
onSubmit (missingAltText, overridePrivacy = null) {
if (missingAltText) {
dispatch(openModal({
modalType: 'CONFIRM_MISSING_ALT_TEXT',
modalProps: { overridePrivacy },
}));
} else {
dispatch(submitCompose(overridePrivacy));
}
},

onClearSuggestions () {
Expand All @@ -110,25 +99,6 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(insertEmojiCompose(position, data, needsSpace));
},

onMediaDescriptionConfirm (mediaId, overridePrivacy = null) {
dispatch(openModal({
modalType: 'CONFIRM',
modalProps: {
message: intl.formatMessage(messages.missingDescriptionMessage),
confirm: intl.formatMessage(messages.missingDescriptionConfirm),
onConfirm: () => {
dispatch(submitCompose(overridePrivacy));
},
secondary: intl.formatMessage(messages.missingDescriptionEdit),
onSecondary: () => dispatch(openModal({
modalType: 'FOCAL_POINT',
modalProps: { id: mediaId },
})),
onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_missing_media_description'], false)),
},
}));
},

});

export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(ComposeForm));
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,6 @@ class LocalSettingsPage extends PureComponent {
<FormattedMessage id='settings.preselect_on_reply' defaultMessage='Pre-select usernames on reply' />
<span className='hint'><FormattedMessage id='settings.preselect_on_reply_hint' defaultMessage='When replying to a conversation with multiple participants, pre-select usernames past the first' /></span>
</LocalSettingsPageItem>
<LocalSettingsPageItem
settings={settings}
item={['confirm_missing_media_description']}
id='mastodon-settings--confirm_missing_media_description'
onChange={onChange}
>
<FormattedMessage id='settings.confirm_missing_media_description' defaultMessage='Show confirmation dialog before sending toots lacking media descriptions' />
</LocalSettingsPageItem>
<LocalSettingsPageItem
settings={settings}
item={['confirm_before_clearing_draft']}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,22 @@ export const ConfirmationModal: React.FC<

<div className='safety-action-modal__bottom'>
<div className='safety-action-modal__actions'>
{secondary && (
<>
<Button onClick={handleSecondary}>{secondary}</Button>

<div className='spacer' />
</>
)}

<button onClick={handleCancel} className='link-button'>
<FormattedMessage
id='confirmation_modal.cancel'
defaultMessage='Cancel'
/>
</button>

{secondary && (
<>
<div className='spacer' />
<button onClick={handleSecondary} className='link-button'>
{secondary}
</button>
</>
)}

{/* eslint-disable-next-line jsx-a11y/no-autofocus -- we are in a modal and thus autofocusing is justified */}
<Button onClick={handleClick} autoFocus>
{confirm}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export { ConfirmUnfollowModal } from './unfollow';
export { ConfirmClearNotificationsModal } from './clear_notifications';
export { ConfirmLogOutModal } from './log_out';
export { ConfirmFollowToListModal } from './follow_to_list';
export { ConfirmMissingAltTextModal } from './missing_alt_text';
Loading

0 comments on commit 29e0edb

Please sign in to comment.