From 04b7046be1fd44baf304559e0c69087d101b358f Mon Sep 17 00:00:00 2001 From: Michael Stanclift Date: Tue, 3 Dec 2024 02:38:23 -0600 Subject: [PATCH 1/7] Provide option to force use of system scrollbar styling (#32117) --- app/helpers/application_helper.rb | 1 + .../styles/mastodon-light/diff.scss | 18 +++++----- app/javascript/styles/mastodon/reset.scss | 36 ++++++++++--------- app/models/concerns/user/has_settings.rb | 4 +++ app/models/user_settings.rb | 1 + .../preferences/appearance/show.html.haml | 1 + config/locales/simple_form.en.yml | 2 ++ 7 files changed, 38 insertions(+), 25 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 9861ee7e8e..e1ca536c7d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -147,6 +147,7 @@ module ApplicationHelper output << content_for(:body_classes) output << "theme-#{current_theme.parameterize}" output << 'system-font' if current_account&.user&.setting_system_font_ui + output << 'custom-scrollbars' unless current_account&.user&.setting_system_scrollbars_ui output << (current_account&.user&.setting_reduce_motion ? 'reduce-motion' : 'no-reduce-motion') output << 'rtl' if locale_direction == 'rtl' output.compact_blank.join(' ') diff --git a/app/javascript/styles/mastodon-light/diff.scss b/app/javascript/styles/mastodon-light/diff.scss index b19075139a..21da3575f5 100644 --- a/app/javascript/styles/mastodon-light/diff.scss +++ b/app/javascript/styles/mastodon-light/diff.scss @@ -523,6 +523,13 @@ a.sparkline { } } +.notification-group--annual-report { + .notification-group__icon, + .notification-group__main .link-button { + color: var(--indigo-3); + } +} + @supports not selector(::-webkit-scrollbar) { html { scrollbar-color: rgba($action-button-color, 0.25) @@ -530,13 +537,8 @@ a.sparkline { } } -::-webkit-scrollbar-thumb { - opacity: 0.25; -} - -.notification-group--annual-report { - .notification-group__icon, - .notification-group__main .link-button { - color: var(--indigo-3); +.custom-scrollbars { + ::-webkit-scrollbar-thumb { + opacity: 0.25; } } diff --git a/app/javascript/styles/mastodon/reset.scss b/app/javascript/styles/mastodon/reset.scss index fc0305baf3..d1ca4a1837 100644 --- a/app/javascript/styles/mastodon/reset.scss +++ b/app/javascript/styles/mastodon/reset.scss @@ -59,24 +59,26 @@ table { } } -::-webkit-scrollbar { - width: 8px; - height: 8px; -} +.custom-scrollbars { + ::-webkit-scrollbar { + width: 8px; + height: 8px; + } -::-webkit-scrollbar-thumb { - background-color: $action-button-color; - border: 2px var(--background-border-color); - border-radius: 12px; - width: 6px; - box-shadow: inset 0 0 0 2px var(--background-border-color); -} + ::-webkit-scrollbar-thumb { + background-color: $action-button-color; + border: 2px var(--background-border-color); + border-radius: 12px; + width: 6px; + box-shadow: inset 0 0 0 2px var(--background-border-color); + } -::-webkit-scrollbar-track { - background-color: var(--background-border-color); - border-radius: 0px; -} + ::-webkit-scrollbar-track { + background-color: var(--background-border-color); + border-radius: 0px; + } -::-webkit-scrollbar-corner { - background: transparent; + ::-webkit-scrollbar-corner { + background: transparent; + } } diff --git a/app/models/concerns/user/has_settings.rb b/app/models/concerns/user/has_settings.rb index 1202f2033f..14d2f22c24 100644 --- a/app/models/concerns/user/has_settings.rb +++ b/app/models/concerns/user/has_settings.rb @@ -43,6 +43,10 @@ module User::HasSettings settings['web.use_system_font'] end + def setting_system_scrollbars_ui + settings['web.use_system_scrollbars'] + end + def setting_noindex settings['noindex'] end diff --git a/app/models/user_settings.rb b/app/models/user_settings.rb index 0ae8ab8ec7..7db14407ac 100644 --- a/app/models/user_settings.rb +++ b/app/models/user_settings.rb @@ -24,6 +24,7 @@ class UserSettings setting :use_blurhash, default: true setting :use_pending_items, default: false setting :use_system_font, default: false + setting :use_system_scrollbars, default: false setting :disable_swiping, default: false setting :disable_hover_cards, default: false setting :delete_modal, default: true diff --git a/app/views/settings/preferences/appearance/show.html.haml b/app/views/settings/preferences/appearance/show.html.haml index 1239b8bcd9..08cfea5a4f 100644 --- a/app/views/settings/preferences/appearance/show.html.haml +++ b/app/views/settings/preferences/appearance/show.html.haml @@ -59,6 +59,7 @@ = ff.input :'web.disable_swiping', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_disable_swiping') = ff.input :'web.disable_hover_cards', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_disable_hover_cards') = ff.input :'web.use_system_font', wrapper: :with_label, label: I18n.t('simple_form.labels.defaults.setting_system_font_ui') + = ff.input :'web.use_system_scrollbars', wrapper: :with_label, hint: I18n.t('simple_form.hints.defaults.setting_system_scrollbars_ui'), label: I18n.t('simple_form.labels.defaults.setting_system_scrollbars_ui') %h4= t 'appearance.discovery' diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml index f451c780b0..b6b0481368 100644 --- a/config/locales/simple_form.en.yml +++ b/config/locales/simple_form.en.yml @@ -60,6 +60,7 @@ en: setting_display_media_default: Hide media marked as sensitive setting_display_media_hide_all: Always hide media setting_display_media_show_all: Always show media + setting_system_scrollbars_ui: Applies only to desktop browsers based on Safari and Chrome setting_use_blurhash: Gradients are based on the colors of the hidden visuals but obfuscate any details setting_use_pending_items: Hide timeline updates behind a click instead of automatically scrolling the feed username: You can use letters, numbers, and underscores @@ -223,6 +224,7 @@ en: setting_hide_network: Hide your social graph setting_reduce_motion: Reduce motion in animations setting_system_font_ui: Use system's default font + setting_system_scrollbars_ui: Use system's default scrollbar setting_theme: Site theme setting_trends: Show today's trends setting_unfollow_modal: Show confirmation dialog before unfollowing someone From ada5baf0b2a0d1a4ef538d5196168aeeb46b5f9b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Dec 2024 08:39:54 +0000 Subject: [PATCH 2/7] Update dependency nokogiri to v1.16.8 (#33140) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index c35bf1a9a3..701ddd7821 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -426,7 +426,7 @@ GEM net-smtp (0.5.0) net-protocol nio4r (2.7.4) - nokogiri (1.16.7) + nokogiri (1.16.8) mini_portile2 (~> 2.8.2) racc (~> 1.4) oj (3.16.7) From 88ff1c8e7e5ee2386afff57caee8aa10eb8a4f59 Mon Sep 17 00:00:00 2001 From: YOCKOW Date: Tue, 3 Dec 2024 17:46:11 +0900 Subject: [PATCH 3/7] Fix typo in CHANGELOG.md (#33145) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 240f6d1532..ebc166a48a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -399,7 +399,7 @@ The following changelog entries focus on changes visible to users, administrator - Fix empty environment variables not using default nil value (#27400 by @renchap) - Fix language sorting in settings (#27158 by @gunchleoc) -## |4.2.11] - 2024-08-16 +## [4.2.11] - 2024-08-16 ### Added From 6cf87762a4fffd3d35c2e4c98900df5867be12eb Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 3 Dec 2024 09:57:29 +0100 Subject: [PATCH 4/7] Change percentile label in year in review in web UI (#33148) --- .../mastodon/features/annual_report/percentile.tsx | 5 ++++- app/javascript/mastodon/locales/en.json | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/features/annual_report/percentile.tsx b/app/javascript/mastodon/features/annual_report/percentile.tsx index 22962019a1..0cfa7d18b9 100644 --- a/app/javascript/mastodon/features/annual_report/percentile.tsx +++ b/app/javascript/mastodon/features/annual_report/percentile.tsx @@ -1,6 +1,7 @@ /* eslint-disable react/jsx-no-useless-fragment */ import { FormattedMessage, FormattedNumber } from 'react-intl'; +import { domain } from 'mastodon/initial_state'; import type { Percentiles } from 'mastodon/models/annual_report'; export const Percentile: React.FC<{ @@ -12,7 +13,7 @@ export const Percentile: React.FC<{
(
@@ -44,6 +45,8 @@ export const Percentile: React.FC<{ )}
), + + domain, }} > {(message) => <>{message}} diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index a02eb7741b..4c7dcb57ec 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -103,7 +103,7 @@ "annual_report.summary.most_used_hashtag.most_used_hashtag": "most used hashtag", "annual_report.summary.most_used_hashtag.none": "None", "annual_report.summary.new_posts.new_posts": "new posts", - "annual_report.summary.percentile.text": "That puts you in the topof Mastodon users.", + "annual_report.summary.percentile.text": "That puts you in the topof {domain} users.", "annual_report.summary.percentile.we_wont_tell_bernie": "We won't tell Bernie.", "annual_report.summary.thanks": "Thanks for being part of Mastodon!", "attachments_list.unprocessed": "(unprocessed)", From 7135f513a45460742b87c7db88e3e280e3a7a060 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Tue, 3 Dec 2024 10:42:52 +0100 Subject: [PATCH 5/7] Add ability to search for all accounts when creating a list in web UI (#33036) --- app/javascript/mastodon/actions/alerts.js | 66 ----- app/javascript/mastodon/actions/alerts.ts | 90 +++++++ app/javascript/mastodon/api/accounts.ts | 13 + .../mastodon/components/account.jsx | 175 ------------- .../mastodon/components/account.tsx | 235 ++++++++++++++++++ .../mastodon/components/empty_account.tsx | 33 --- .../mastodon/components/server_banner.jsx | 2 +- .../mastodon/containers/account_container.jsx | 60 ----- .../mastodon/features/about/index.jsx | 2 +- .../mastodon/features/blocks/index.jsx | 4 +- .../compose/components/navigation_bar.jsx | 5 +- .../compose/components/search_results.jsx | 4 +- .../mastodon/features/explore/results.jsx | 2 +- .../mastodon/features/favourites/index.jsx | 4 +- .../mastodon/features/followers/index.jsx | 4 +- .../mastodon/features/following/index.jsx | 4 +- .../mastodon/features/lists/members.tsx | 54 +++- .../mastodon/features/mutes/index.jsx | 4 +- .../notifications/components/notification.jsx | 8 +- .../mastodon/features/onboarding/follows.tsx | 9 +- .../mastodon/features/reblogs/index.jsx | 4 +- .../confirmation_modals/follow_to_list.tsx | 43 ++++ .../components/confirmation_modals/index.ts | 1 + .../features/ui/components/modal_root.jsx | 2 + app/javascript/mastodon/locales/en.json | 5 +- 25 files changed, 459 insertions(+), 374 deletions(-) delete mode 100644 app/javascript/mastodon/actions/alerts.js create mode 100644 app/javascript/mastodon/actions/alerts.ts delete mode 100644 app/javascript/mastodon/components/account.jsx create mode 100644 app/javascript/mastodon/components/account.tsx delete mode 100644 app/javascript/mastodon/components/empty_account.tsx delete mode 100644 app/javascript/mastodon/containers/account_container.jsx create mode 100644 app/javascript/mastodon/features/ui/components/confirmation_modals/follow_to_list.tsx diff --git a/app/javascript/mastodon/actions/alerts.js b/app/javascript/mastodon/actions/alerts.js deleted file mode 100644 index 48dee2587f..0000000000 --- a/app/javascript/mastodon/actions/alerts.js +++ /dev/null @@ -1,66 +0,0 @@ -import { defineMessages } from 'react-intl'; - -import { AxiosError } from 'axios'; - -const messages = defineMessages({ - unexpectedTitle: { id: 'alert.unexpected.title', defaultMessage: 'Oops!' }, - unexpectedMessage: { id: 'alert.unexpected.message', defaultMessage: 'An unexpected error occurred.' }, - rateLimitedTitle: { id: 'alert.rate_limited.title', defaultMessage: 'Rate limited' }, - rateLimitedMessage: { id: 'alert.rate_limited.message', defaultMessage: 'Please retry after {retry_time, time, medium}.' }, -}); - -export const ALERT_SHOW = 'ALERT_SHOW'; -export const ALERT_DISMISS = 'ALERT_DISMISS'; -export const ALERT_CLEAR = 'ALERT_CLEAR'; -export const ALERT_NOOP = 'ALERT_NOOP'; - -export const dismissAlert = alert => ({ - type: ALERT_DISMISS, - alert, -}); - -export const clearAlert = () => ({ - type: ALERT_CLEAR, -}); - -export const showAlert = alert => ({ - type: ALERT_SHOW, - alert, -}); - -export const showAlertForError = (error, skipNotFound = false) => { - if (error.response) { - const { data, status, statusText, headers } = error.response; - - // Skip these errors as they are reflected in the UI - if (skipNotFound && (status === 404 || status === 410)) { - return { type: ALERT_NOOP }; - } - - // Rate limit errors - if (status === 429 && headers['x-ratelimit-reset']) { - return showAlert({ - title: messages.rateLimitedTitle, - message: messages.rateLimitedMessage, - values: { 'retry_time': new Date(headers['x-ratelimit-reset']) }, - }); - } - - return showAlert({ - title: `${status}`, - message: data.error || statusText, - }); - } - - // An aborted request, e.g. due to reloading the browser window, it not really error - if (error.code === AxiosError.ECONNABORTED) { - return { type: ALERT_NOOP }; - } - - console.error(error); - - return showAlert({ - title: messages.unexpectedTitle, - message: messages.unexpectedMessage, - }); -}; diff --git a/app/javascript/mastodon/actions/alerts.ts b/app/javascript/mastodon/actions/alerts.ts new file mode 100644 index 0000000000..a521f3ef35 --- /dev/null +++ b/app/javascript/mastodon/actions/alerts.ts @@ -0,0 +1,90 @@ +import { defineMessages } from 'react-intl'; +import type { MessageDescriptor } from 'react-intl'; + +import { AxiosError } from 'axios'; +import type { AxiosResponse } from 'axios'; + +interface Alert { + title: string | MessageDescriptor; + message: string | MessageDescriptor; + values?: Record; +} + +interface ApiErrorResponse { + error?: string; +} + +const messages = defineMessages({ + unexpectedTitle: { id: 'alert.unexpected.title', defaultMessage: 'Oops!' }, + unexpectedMessage: { + id: 'alert.unexpected.message', + defaultMessage: 'An unexpected error occurred.', + }, + rateLimitedTitle: { + id: 'alert.rate_limited.title', + defaultMessage: 'Rate limited', + }, + rateLimitedMessage: { + id: 'alert.rate_limited.message', + defaultMessage: 'Please retry after {retry_time, time, medium}.', + }, +}); + +export const ALERT_SHOW = 'ALERT_SHOW'; +export const ALERT_DISMISS = 'ALERT_DISMISS'; +export const ALERT_CLEAR = 'ALERT_CLEAR'; +export const ALERT_NOOP = 'ALERT_NOOP'; + +export const dismissAlert = (alert: Alert) => ({ + type: ALERT_DISMISS, + alert, +}); + +export const clearAlert = () => ({ + type: ALERT_CLEAR, +}); + +export const showAlert = (alert: Alert) => ({ + type: ALERT_SHOW, + alert, +}); + +export const showAlertForError = (error: unknown, skipNotFound = false) => { + if (error instanceof AxiosError && error.response) { + const { status, statusText, headers } = error.response; + const { data } = error.response as AxiosResponse; + + // Skip these errors as they are reflected in the UI + if (skipNotFound && (status === 404 || status === 410)) { + return { type: ALERT_NOOP }; + } + + // Rate limit errors + if (status === 429 && headers['x-ratelimit-reset']) { + return showAlert({ + title: messages.rateLimitedTitle, + message: messages.rateLimitedMessage, + values: { + retry_time: new Date(headers['x-ratelimit-reset'] as string), + }, + }); + } + + return showAlert({ + title: `${status}`, + message: data.error ?? statusText, + }); + } + + // An aborted request, e.g. due to reloading the browser window, it not really error + if (error instanceof AxiosError && error.code === AxiosError.ECONNABORTED) { + return { type: ALERT_NOOP }; + } + + console.error(error); + + return showAlert({ + title: messages.unexpectedTitle, + message: messages.unexpectedMessage, + }); +}; diff --git a/app/javascript/mastodon/api/accounts.ts b/app/javascript/mastodon/api/accounts.ts index bd1757e827..717010ba74 100644 --- a/app/javascript/mastodon/api/accounts.ts +++ b/app/javascript/mastodon/api/accounts.ts @@ -5,3 +5,16 @@ export const apiSubmitAccountNote = (id: string, value: string) => apiRequestPost(`v1/accounts/${id}/note`, { comment: value, }); + +export const apiFollowAccount = ( + id: string, + params?: { + reblogs: boolean; + }, +) => + apiRequestPost(`v1/accounts/${id}/follow`, { + ...params, + }); + +export const apiUnfollowAccount = (id: string) => + apiRequestPost(`v1/accounts/${id}/unfollow`); diff --git a/app/javascript/mastodon/components/account.jsx b/app/javascript/mastodon/components/account.jsx deleted file mode 100644 index fa66fd56bb..0000000000 --- a/app/javascript/mastodon/components/account.jsx +++ /dev/null @@ -1,175 +0,0 @@ -import PropTypes from 'prop-types'; -import { useCallback } from 'react'; - -import { defineMessages, useIntl, FormattedMessage } from 'react-intl'; - -import classNames from 'classnames'; -import { Link } from 'react-router-dom'; - -import ImmutablePropTypes from 'react-immutable-proptypes'; - -import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react'; -import { EmptyAccount } from 'mastodon/components/empty_account'; -import { FollowButton } from 'mastodon/components/follow_button'; -import { ShortNumber } from 'mastodon/components/short_number'; -import { VerifiedBadge } from 'mastodon/components/verified_badge'; - -import DropdownMenuContainer from '../containers/dropdown_menu_container'; -import { me } from '../initial_state'; - -import { Avatar } from './avatar'; -import { Button } from './button'; -import { FollowersCounter } from './counters'; -import { DisplayName } from './display_name'; -import { RelativeTimestamp } from './relative_timestamp'; - -const messages = defineMessages({ - unblock: { id: 'account.unblock_short', defaultMessage: 'Unblock' }, - unmute: { id: 'account.unmute_short', defaultMessage: 'Unmute' }, - mute_notifications: { id: 'account.mute_notifications_short', defaultMessage: 'Mute notifications' }, - unmute_notifications: { id: 'account.unmute_notifications_short', defaultMessage: 'Unmute notifications' }, - mute: { id: 'account.mute_short', defaultMessage: 'Mute' }, - block: { id: 'account.block_short', defaultMessage: 'Block' }, - more: { id: 'status.more', defaultMessage: 'More' }, -}); - -const Account = ({ size = 46, account, onBlock, onMute, onMuteNotifications, hidden, minimal, defaultAction, withBio }) => { - const intl = useIntl(); - - const handleBlock = useCallback(() => { - onBlock(account); - }, [onBlock, account]); - - const handleMute = useCallback(() => { - onMute(account); - }, [onMute, account]); - - const handleMuteNotifications = useCallback(() => { - onMuteNotifications(account, true); - }, [onMuteNotifications, account]); - - const handleUnmuteNotifications = useCallback(() => { - onMuteNotifications(account, false); - }, [onMuteNotifications, account]); - - if (!account) { - return ; - } - - if (hidden) { - return ( - <> - {account.get('display_name')} - {account.get('username')} - - ); - } - - let buttons; - - if (account.get('id') !== me && account.get('relationship', null) !== null) { - const requested = account.getIn(['relationship', 'requested']); - const blocking = account.getIn(['relationship', 'blocking']); - const muting = account.getIn(['relationship', 'muting']); - - if (requested) { - buttons = ; - } else if (blocking) { - buttons =
); @@ -167,7 +167,7 @@ class Notification extends ImmutablePureComponent { -