diff --git a/CHANGELOG.md b/CHANGELOG.md
index 56b6fbc92c..bf5dbd2ba9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,23 @@
All notable changes to this project will be documented in this file.
+## [4.5.9] - 2026-04-15
+
+### Security
+
+- Insufficient verification of email addresses ([GHSA-5r37-qpwq-2jhh](https://github.com/mastodon/mastodon/security/advisories/GHSA-5r37-qpwq-2jhh))
+- Updated dependencies
+
+### Added
+
+- Add trademark warning to `mastodon:setup` task (#38548 by @ClearlyClaire)
+
+### Fixed
+
+- Fix definition for `quote` in JSON-LD context (#38686 by @ClearlyClaire)
+- Fix being unable to disable sound for quote update notification (#38537 by @ClearlyClaire)
+- Fix being able to quote someone you blocked (#38608 by @ClearlyClaire)
+
## [4.5.8] - 2026-03-24
### Security
diff --git a/README.md b/README.md
index 3bf5968b64..e4b25b1716 100644
--- a/README.md
+++ b/README.md
@@ -20,7 +20,7 @@ Mastodon Glitch Edition is a fork of [Mastodon](https://github.com/mastodon/mast
-
+
diff --git a/app/javascript/images/elephant_ui.svg b/app/javascript/images/elephant_ui.svg
new file mode 100644
index 0000000000..88b23841ff
--- /dev/null
+++ b/app/javascript/images/elephant_ui.svg
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/javascript/images/elephant_ui_dark.svg b/app/javascript/images/elephant_ui_dark.svg
deleted file mode 100644
index aa91b704c7..0000000000
--- a/app/javascript/images/elephant_ui_dark.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/app/javascript/images/elephant_ui_light.svg b/app/javascript/images/elephant_ui_light.svg
deleted file mode 100644
index 1eeab31cf4..0000000000
--- a/app/javascript/images/elephant_ui_light.svg
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/app/javascript/mastodon/components/account/index.tsx b/app/javascript/mastodon/components/account/index.tsx
index d93415f15a..9ec2e13205 100644
--- a/app/javascript/mastodon/components/account/index.tsx
+++ b/app/javascript/mastodon/components/account/index.tsx
@@ -277,7 +277,7 @@ export const Account: React.FC = ({
if (account?.mute_expires_at) {
muteTimeRemaining = (
<>
- ·
+ ·
>
);
}
diff --git a/app/javascript/mastodon/components/account_list_item/index.tsx b/app/javascript/mastodon/components/account_list_item/index.tsx
index 647adbfa79..34ae8b0daf 100644
--- a/app/javascript/mastodon/components/account_list_item/index.tsx
+++ b/app/javascript/mastodon/components/account_list_item/index.tsx
@@ -149,11 +149,7 @@ export const AccountListItem: React.FC = ({
}
>
{account.last_status_at ? (
-
+
) : (
'-'
)}
diff --git a/app/javascript/mastodon/components/badge/index.tsx b/app/javascript/mastodon/components/badge/index.tsx
index f75d50ebe9..1cc4b531c7 100644
--- a/app/javascript/mastodon/components/badge/index.tsx
+++ b/app/javascript/mastodon/components/badge/index.tsx
@@ -52,8 +52,10 @@ export const Badge: FC = ({
data-account-role-id={roleId}
>
{icon}
- {label}
- {domain && {domain} }
+
+ {label}
+ {domain && {domain} }
+
);
diff --git a/app/javascript/mastodon/components/badge/styles.module.scss b/app/javascript/mastodon/components/badge/styles.module.scss
index 59c738b9cc..d359bc38eb 100644
--- a/app/javascript/mastodon/components/badge/styles.module.scss
+++ b/app/javascript/mastodon/components/badge/styles.module.scss
@@ -7,9 +7,9 @@
gap: 4px;
border-radius: 8px;
align-items: center;
- overflow-wrap: anywhere;
> svg {
+ flex-shrink: 0;
width: auto;
height: 17px;
fill: currentColor;
@@ -26,6 +26,12 @@
}
}
+.content {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
.domain {
opacity: 0.75;
letter-spacing: 0;
diff --git a/app/javascript/mastodon/components/poll.tsx b/app/javascript/mastodon/components/poll.tsx
index 3ab31f4229..c77ce8bcee 100644
--- a/app/javascript/mastodon/components/poll.tsx
+++ b/app/javascript/mastodon/components/poll.tsx
@@ -70,7 +70,7 @@ export const Poll: React.FC = ({ pollId, disabled, status }) => {
if (expired) {
return intl.formatMessage(messages.closed);
}
- return ;
+ return ;
}, [expired, intl, poll]);
const votesCount = useMemo(() => {
if (!poll) {
diff --git a/app/javascript/mastodon/components/relative_timestamp/index.tsx b/app/javascript/mastodon/components/relative_timestamp/index.tsx
index 493e535a71..fa6200b7d1 100644
--- a/app/javascript/mastodon/components/relative_timestamp/index.tsx
+++ b/app/javascript/mastodon/components/relative_timestamp/index.tsx
@@ -23,16 +23,16 @@ export const RelativeTimestamp: FC<{
timestamp: string;
long?: boolean;
noTime?: boolean;
- noFuture?: boolean;
-}> = ({ timestamp, long = false, noTime = false, noFuture = false }) => {
+ hasFuture?: boolean;
+}> = ({ timestamp, long = false, noTime = false, hasFuture = false }) => {
const intl = useIntl();
const [now, setNow] = useState(() => Date.now());
const date = useMemo(() => {
const date = new Date(timestamp);
- return noFuture ? new Date(Math.min(date.getTime(), now)) : date;
- }, [noFuture, now, timestamp]);
+ return !hasFuture ? new Date(Math.min(date.getTime(), now)) : date;
+ }, [hasFuture, now, timestamp]);
const ts = date.getTime();
useEffect(() => {
diff --git a/app/javascript/mastodon/components/relative_timestamp/relative_timestamp.stories.tsx b/app/javascript/mastodon/components/relative_timestamp/relative_timestamp.stories.tsx
index 978382515d..96965d3f3a 100644
--- a/app/javascript/mastodon/components/relative_timestamp/relative_timestamp.stories.tsx
+++ b/app/javascript/mastodon/components/relative_timestamp/relative_timestamp.stories.tsx
@@ -11,7 +11,7 @@ const meta = {
timestamp: new Date(Date.now() - DAY * 3).toISOString(),
long: false,
noTime: false,
- noFuture: false,
+ hasFuture: false,
},
argTypes: {
timestamp: {
@@ -44,10 +44,10 @@ export const DateOnly: Story = {
},
};
-export const NoFuture: Story = {
+export const HasFuture: Story = {
args: {
timestamp: new Date(Date.now() + DAY * 3).toISOString(),
- noFuture: true,
+ hasFuture: true,
},
};
diff --git a/app/javascript/mastodon/components/status/header.tsx b/app/javascript/mastodon/components/status/header.tsx
index 9b1445e9c1..65790bb493 100644
--- a/app/javascript/mastodon/components/status/header.tsx
+++ b/app/javascript/mastodon/components/status/header.tsx
@@ -56,10 +56,7 @@ export const StatusHeader: FC = ({
className='status__relative-time'
>
-
+
{editedAt && }
diff --git a/app/javascript/mastodon/components/truncated_list/index.tsx b/app/javascript/mastodon/components/truncated_list/index.tsx
new file mode 100644
index 0000000000..75e5a4ee25
--- /dev/null
+++ b/app/javascript/mastodon/components/truncated_list/index.tsx
@@ -0,0 +1,107 @@
+import { useCallback, useState } from 'react';
+
+import { Article } from '@/mastodon/components/scrollable_list/components';
+import KeyboardArrowDownIcon from '@/material-icons/400-24px/keyboard_arrow_down.svg?react';
+import KeyboardArrowUpIcon from '@/material-icons/400-24px/keyboard_arrow_up.svg?react';
+
+import { Icon } from '../icon';
+import type { IconProp } from '../icon';
+import { ListItemButton, ListItemWrapper } from '../list_item';
+
+export interface TruncatedListItemInfo {
+ item: TListItem;
+ index: number;
+ totalListLength: number;
+ isLastElement: boolean;
+}
+
+interface ToggleButtonOptions {
+ title: NonNullable;
+ subtitle?: React.ReactNode;
+ icon?: IconProp;
+}
+
+interface TruncatedListProps {
+ visibleItems: TListItem[];
+ truncatedItems: TListItem[];
+ renderListItem: (
+ itemInfo: TruncatedListItemInfo,
+ ) => React.ReactElement;
+ toggleButton: ToggleButtonOptions;
+}
+
+/**
+ * Truncate the children of an `ItemList` component with this helper
+ * component.
+ * It handles rendering the children with correct indexes for accessibility,
+ * and has a configurable toggle button.
+ */
+export const TruncatedListItems = ({
+ visibleItems,
+ truncatedItems,
+ toggleButton,
+ renderListItem,
+}: TruncatedListProps) => {
+ const [showTruncatedItems, setShowTruncatedItems] = useState(false);
+ const toggleTruncatedItems = useCallback(() => {
+ setShowTruncatedItems((prev) => !prev);
+ }, []);
+
+ const hasHiddenAccounts = truncatedItems.length > 0;
+ // Add the toggle button's item to the list size when needed
+ const initialListSize = visibleItems.length + (hasHiddenAccounts ? 1 : 0);
+ const totalListLength =
+ initialListSize + (showTruncatedItems ? truncatedItems.length : 0);
+
+ return (
+ <>
+ {visibleItems.map((item, index) => {
+ return renderListItem({
+ item,
+ index,
+ totalListLength,
+ isLastElement:
+ index === visibleItems.length - 1 && !hasHiddenAccounts,
+ });
+ })}
+ {hasHiddenAccounts && (
+
+
+ )
+ }
+ iconEnd={
+
+ }
+ >
+
+ {toggleButton.title}
+
+
+
+ )}
+ {showTruncatedItems &&
+ truncatedItems.map((item, index) => {
+ return renderListItem({
+ item,
+ index: initialListSize + index + 1,
+ totalListLength,
+ isLastElement: index === truncatedItems.length - 1,
+ });
+ })}
+ >
+ );
+};
diff --git a/app/javascript/mastodon/features/account_featured/components/empty_message.module.scss b/app/javascript/mastodon/features/account_featured/components/empty_message.module.scss
new file mode 100644
index 0000000000..25dcf19433
--- /dev/null
+++ b/app/javascript/mastodon/features/account_featured/components/empty_message.module.scss
@@ -0,0 +1,8 @@
+[data-color-scheme='dark'] .image {
+ --color-skin-1: #3a3a50;
+ --color-skin-2: #67678e;
+ --color-skin-3: #44445f;
+ --color-outline: #21212c;
+ --color-shadow: #181820;
+ --color-highlight: #b2b1c8;
+}
diff --git a/app/javascript/mastodon/features/account_featured/components/empty_message.tsx b/app/javascript/mastodon/features/account_featured/components/empty_message.tsx
index 2503de2aa0..35b67cd641 100644
--- a/app/javascript/mastodon/features/account_featured/components/empty_message.tsx
+++ b/app/javascript/mastodon/features/account_featured/components/empty_message.tsx
@@ -5,17 +5,17 @@ import { FormattedMessage } from 'react-intl';
import { useParams } from 'react-router';
import { Link } from 'react-router-dom';
-import ElephantDarkImage from '@/images/elephant_ui_dark.svg?react';
-import ElephantLightImage from '@/images/elephant_ui_light.svg?react';
+import ElephantImage from '@/images/elephant_ui.svg?react';
import { openModal } from '@/mastodon/actions/modal';
import { Button } from '@/mastodon/components/button';
import { EmptyState } from '@/mastodon/components/empty_state';
import { LimitedAccountHint } from '@/mastodon/features/account_timeline/components/limited_account_hint';
import { areCollectionsEnabled } from '@/mastodon/features/collections/utils';
import { useCurrentAccountId } from '@/mastodon/hooks/useAccountId';
-import { useTheme } from '@/mastodon/hooks/useTheme';
import { useAppDispatch } from '@/mastodon/store';
+import classes from './empty_message.module.scss';
+
interface EmptyMessageProps {
suspended: boolean;
hidden: boolean;
@@ -33,9 +33,6 @@ export const EmptyMessage: React.FC = ({
}) => {
const { acct } = useParams<{ acct?: string }>();
const me = useCurrentAccountId();
- const theme = useTheme();
- const ElephantImage =
- theme === 'dark' ? ElephantDarkImage : ElephantLightImage;
const dispatch = useAppDispatch();
@@ -57,7 +54,7 @@ export const EmptyMessage: React.FC = ({
const hasCollections = areCollectionsEnabled();
- const image = ;
+ const image = ;
if (me === accountId) {
if (hasCollections) {
diff --git a/app/javascript/mastodon/features/account_featured/index.tsx b/app/javascript/mastodon/features/account_featured/index.tsx
index 1b83b66dfd..9acb7ff65c 100644
--- a/app/javascript/mastodon/features/account_featured/index.tsx
+++ b/app/javascript/mastodon/features/account_featured/index.tsx
@@ -1,4 +1,4 @@
-import { useEffect } from 'react';
+import { useCallback, useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
@@ -6,10 +6,9 @@ import { useHistory } from 'react-router';
import { List as ImmutableList } from 'immutable';
-import { AccountListItem } from '@/mastodon/components/account_list_item';
-import { useAccount } from '@/mastodon/hooks/useAccount';
import AddIcon from '@/material-icons/400-24px/add.svg?react';
import { fetchEndorsedAccounts } from 'mastodon/actions/accounts';
+import { AccountListItem } from 'mastodon/components/account_list_item';
import { ColumnBackButton } from 'mastodon/components/column_back_button';
import { LoadingIndicator } from 'mastodon/components/loading_indicator';
import { RemoteHint } from 'mastodon/components/remote_hint';
@@ -18,9 +17,12 @@ import {
ItemList,
Scrollable,
} from 'mastodon/components/scrollable_list/components';
+import type { TruncatedListItemInfo } from 'mastodon/components/truncated_list';
+import { TruncatedListItems } from 'mastodon/components/truncated_list';
import { AccountHeader } from 'mastodon/features/account_timeline/components/account_header';
import BundleColumnError from 'mastodon/features/ui/components/bundle_column_error';
import Column from 'mastodon/features/ui/components/column';
+import { useAccount } from 'mastodon/hooks/useAccount';
import { useAccountId } from 'mastodon/hooks/useAccountId';
import { useAccountVisibility } from 'mastodon/hooks/useAccountVisibility';
import {
@@ -74,11 +76,32 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
const { collections, status: collectionsLoadStatus } = useAppSelector(
(state) => selectAccountCollections(state, accountId ?? null),
);
- const listedCollections = collections.filter(
- // Hide unlisted and empty collections to avoid confusion
- // (Unlisted collections will only be part of the payload
- // when viewing your own profile.)
- (item) => item.discoverable && !!item.item_count,
+
+ const { listedCollections = [], unlistedCollections = [] } = Object.groupBy(
+ collections,
+ (item) =>
+ item.discoverable && !!item.item_count
+ ? 'listedCollections'
+ : 'unlistedCollections',
+ );
+
+ const renderListItem = useCallback(
+ ({
+ item,
+ index,
+ totalListLength,
+ isLastElement,
+ }: TruncatedListItemInfo<(typeof listedCollections)[number]>) => (
+
+ ),
+ [],
);
const hasCollections =
@@ -167,16 +190,26 @@ const AccountFeatured: React.FC<{ multiColumn: boolean }> = ({
{hasCollections ? (
- {listedCollections.map((item, index) => (
-
- ))}
+
+ ),
+ subtitle: (
+
+ ),
+ }}
+ renderListItem={renderListItem}
+ />
) : (
= ({
className='status__relative-time'
>
-
+
{editedAt && }
diff --git a/app/javascript/mastodon/features/collections/detail/accounts_list.tsx b/app/javascript/mastodon/features/collections/detail/accounts_list.tsx
index affbd9ad03..1127bdad24 100644
--- a/app/javascript/mastodon/features/collections/detail/accounts_list.tsx
+++ b/app/javascript/mastodon/features/collections/detail/accounts_list.tsx
@@ -2,13 +2,6 @@ import { useCallback, useMemo, useRef, useState } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
-import {
- ListItemButton,
- ListItemWrapper,
-} from '@/mastodon/components/list_item';
-import { createAppSelector, useAppSelector } from '@/mastodon/store';
-import KeyboardArrowDownIcon from '@/material-icons/400-24px/keyboard_arrow_down.svg?react';
-import KeyboardArrowUpIcon from '@/material-icons/400-24px/keyboard_arrow_up.svg?react';
import VisibilityOffIcon from '@/material-icons/400-24px/visibility_off.svg?react';
import type { ApiCollectionJSON } from 'mastodon/api_types/collections';
import type { RenderButtonOptions } from 'mastodon/components/account_list_item';
@@ -18,13 +11,15 @@ import {
} from 'mastodon/components/account_list_item';
import { Button } from 'mastodon/components/button';
import { Callout } from 'mastodon/components/callout';
-import { Icon } from 'mastodon/components/icon';
import {
Article,
ItemList,
} from 'mastodon/components/scrollable_list/components';
+import type { TruncatedListItemInfo } from 'mastodon/components/truncated_list';
+import { TruncatedListItems } from 'mastodon/components/truncated_list';
import { me } from 'mastodon/initial_state';
import type { Account } from 'mastodon/models/account';
+import { createAppSelector, useAppSelector } from 'mastodon/store';
import { useConfirmRevoke } from './revoke_collection_inclusion_modal';
import classes from './styles.module.scss';
@@ -99,13 +94,9 @@ export const CollectionAccountsList: React.FC<{
const intl = useIntl();
const confirmRevoke = useConfirmRevoke(collection);
const listHeadingRef = useRef(null);
- const [canShowHiddenAccounts, setCanShowHiddenAccounts] = useState(false);
- const toggleHiddenAccounts = useCallback(() => {
- setCanShowHiddenAccounts((prev) => !prev);
- }, []);
const isOwnCollection = collection?.account_id === me;
- const { items = [], account_id: collectionOwnerId, id } = collection ?? {};
+ const { account_id: collectionOwnerId, id } = collection ?? {};
const relationships = useAppSelector((state) => state.relationships);
const collectionAccounts = useAppSelector((state) =>
@@ -135,9 +126,6 @@ export const CollectionAccountsList: React.FC<{
return { visibleAccounts, hiddenAccounts };
}, [collectionAccounts, relationships]);
- const hasHiddenAccounts = hiddenAccounts.length > 0;
- const initialListSize = visibleAccounts.length + (hasHiddenAccounts ? 1 : 0);
-
const renderAccountItemButton = useCallback(
({ relationship, accountId }: RenderButtonOptions) => {
// When viewing your own collection, only show the Follow button
@@ -165,6 +153,28 @@ export const CollectionAccountsList: React.FC<{
[collectionOwnerId, confirmRevoke],
);
+ const renderListItem = useCallback(
+ ({
+ item,
+ index,
+ totalListLength,
+ isLastElement,
+ }: TruncatedListItemInfo) => (
+
+
+
+ ),
+ [renderAccountItemButton],
+ );
+
return (
<>
- {visibleAccounts.map(({ id }, index) => (
-
-
-
- ))}
- {hasHiddenAccounts && (
-
- }
- iconEnd={
-
- }
- >
-
- }
- >
-
-
-
-
- )}
- {canShowHiddenAccounts &&
- hiddenAccounts.map(({ id }, index) => (
-
-
-
- ))}
+ ),
+ subtitle: (
+
+ ),
+ }}
+ renderListItem={renderListItem}
+ />
)}
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 76bf0fba87..8b05678fc7 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -409,6 +409,8 @@
"collections.sensitive": "Sensitive",
"collections.topic_hint": "Add a hashtag that helps others understand the main topic of this collection.",
"collections.topic_special_chars_hint": "Special characters will be removed when saving",
+ "collections.unlisted_collections_description": "These don’t appear on your profile to others. Anyone with the link can discover them.",
+ "collections.unlisted_collections_with_count": "Unlisted collections ({count})",
"collections.view_collection": "View collection",
"collections.view_other_collections_by_user": "View other collections by this user",
"collections.visibility_public": "Public",
diff --git a/app/javascript/styles/mastodon/components.scss b/app/javascript/styles/mastodon/components.scss
index e172591ba6..2349bc74de 100644
--- a/app/javascript/styles/mastodon/components.scss
+++ b/app/javascript/styles/mastodon/components.scss
@@ -10657,14 +10657,7 @@ noscript {
}
&__source {
- overflow: hidden;
- white-space: nowrap;
cursor: help;
-
- > span {
- overflow: hidden;
- text-overflow: ellipsis;
- }
}
}
diff --git a/app/models/email_subscription.rb b/app/models/email_subscription.rb
index fc3a0f125d..b108ef19c5 100644
--- a/app/models/email_subscription.rb
+++ b/app/models/email_subscription.rb
@@ -19,7 +19,7 @@ class EmailSubscription < ApplicationRecord
normalizes :email, with: ->(str) { str.squish.downcase }
- validates :email, presence: true, email_address: true, uniqueness: { scope: :account_id }
+ validates :email, presence: true, email_address: true, length: { maximum: 320 }, uniqueness: { scope: :account_id }
validates :email, email_mx: true, if: -> { email_changed? && !Rails.env.local? }
scope :confirmed, -> { where.not(confirmed_at: nil) }
diff --git a/app/models/user.rb b/app/models/user.rb
index 7b53c0e4f8..461e7089fc 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -92,7 +92,7 @@ class User < ApplicationRecord
accepts_nested_attributes_for :invite_request, reject_if: ->(attributes) { attributes['text'].blank? && !Setting.require_invite_text }
validates :invite_request, presence: true, on: :create, if: :invite_text_required?
- validates :email, presence: true, email_address: true
+ validates :email, presence: true, email_address: true, length: { maximum: 320 }
validates :email, email_mx: { attempt_ip: :sign_up_ip }, if: :validate_email_dns?
validates_with UserEmailValidator, if: -> { ENV['EMAIL_DOMAIN_LISTS_APPLY_AFTER_CONFIRMATION'] == 'true' || !confirmed? }
diff --git a/app/validators/email_address_validator.rb b/app/validators/email_address_validator.rb
index ed0bb11652..7cc303a636 100644
--- a/app/validators/email_address_validator.rb
+++ b/app/validators/email_address_validator.rb
@@ -11,8 +11,14 @@ class EmailAddressValidator < ActiveModel::EachValidator
value = value.strip
address = Mail::Address.new(value)
- record.errors.add(attribute, :invalid) if address.address != value
+ record.errors.add(attribute, :invalid) if address.address != value || contains_disallowed_characters?(value)
rescue Mail::Field::FieldError
record.errors.add(attribute, :invalid)
end
+
+ private
+
+ def contains_disallowed_characters?(value)
+ value.include?('%') || value.include?(',') || value.include?('"')
+ end
end
diff --git a/docker-compose.yml b/docker-compose.yml
index 72b087e34a..e1ea73cda2 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -59,7 +59,7 @@ services:
web:
# You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes
# build: .
- image: ghcr.io/glitch-soc/mastodon:v4.5.8
+ image: ghcr.io/glitch-soc/mastodon:v4.5.9
restart: always
env_file: .env.production
command: bundle exec puma -C config/puma.rb
@@ -83,7 +83,7 @@ services:
# build:
# dockerfile: ./streaming/Dockerfile
# context: .
- image: ghcr.io/glitch-soc/mastodon-streaming:v4.5.8
+ image: ghcr.io/glitch-soc/mastodon-streaming:v4.5.9
restart: always
env_file: .env.production
command: node ./streaming/index.js
@@ -102,7 +102,7 @@ services:
sidekiq:
# You can uncomment the following line if you want to not use the prebuilt image, for example if you have local code changes
# build: .
- image: ghcr.io/glitch-soc/mastodon:v4.5.8
+ image: ghcr.io/glitch-soc/mastodon:v4.5.9
restart: always
env_file: .env.production
command: bundle exec sidekiq
diff --git a/docs/hero-nodes.gif b/docs/hero-nodes.gif
new file mode 100644
index 0000000000..5692e2ef7c
Binary files /dev/null and b/docs/hero-nodes.gif differ
diff --git a/lib/mastodon/version.rb b/lib/mastodon/version.rb
index 2e82d2844b..2a61199c05 100644
--- a/lib/mastodon/version.rb
+++ b/lib/mastodon/version.rb
@@ -17,7 +17,7 @@ module Mastodon
end
def default_prerelease
- 'alpha.6'
+ 'alpha.7'
end
def prerelease