Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge upstream changes up to f79b96a5ef0f6c4f57eee7f44ce2579b28a22098 #2962

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
1e70da5
Add reminder when about to post without alt text in web UI (#33760)
Gargron Jan 29, 2025
2d545c5
Fix flaky test in `/api/v2/notifications` tests (#33773)
ClearlyClaire Jan 29, 2025
796187c
Add ability to dismiss alt text badge by tapping it in web UI (#33737)
Gargron Jan 29, 2025
7ffda06
build(Dockerfiles): Set the base registry via an ARG (#33712)
wolfspyre Jan 29, 2025
e53c8fb
Fix `PollExpirationValidator` redundant check for `expires_at` presen…
ClearlyClaire Jan 29, 2025
005b2ba
chore(deps): update dependency pino-pretty to v13 (#33778)
renovate[bot] Jan 29, 2025
3f4f631
New Crowdin Translations (automated) (#33787)
github-actions[bot] Jan 30, 2025
a3d2849
Fix `tootctl feeds build` not building list timelines (#33783)
ClearlyClaire Jan 30, 2025
7c03327
chore(deps): update dependency haml_lint to v0.60.0 (#33791)
renovate[bot] Jan 31, 2025
c5cd9bd
Convert `auth/passwords` spec controller->system/request (#33790)
mjankowski Jan 31, 2025
91e4a09
New Crowdin Translations (automated) (#33795)
github-actions[bot] Jan 31, 2025
7758791
Convert `admin/reports` spec controller->system (#33789)
mjankowski Jan 31, 2025
a29fc4b
chore(deps): update dependency puma to v6.6.0 (#33768)
renovate[bot] Jan 31, 2025
f79b96a
chore(deps): update dependency rubocop to v1.71.1 (#33796)
renovate[bot] Jan 31, 2025
c85616e
Merge commit 'f79b96a5ef0f6c4f57eee7f44ce2579b28a22098' into glitch-s…
ClearlyClaire Feb 1, 2025
800bea7
[Glitch] Add ability to dismiss alt text badge by tapping it in web UI
Gargron Jan 29, 2025
a3399ed
[Glitch] Add reminder when about to post without alt text in web UI
Gargron Jan 29, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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