-
+
{name}
diff --git a/app/javascript/mastodon/features/collections/components/collection_menu.tsx b/app/javascript/mastodon/features/collections/components/collection_menu.tsx
index 661e879df5..f5cc518fb8 100644
--- a/app/javascript/mastodon/features/collections/components/collection_menu.tsx
+++ b/app/javascript/mastodon/features/collections/components/collection_menu.tsx
@@ -15,6 +15,7 @@ import type { MenuItem } from 'mastodon/models/dropdown_menu';
import { useAppDispatch } from 'mastodon/store';
import { messages as editorMessages } from '../editor';
+import { getCollectionPath } from '../utils';
const messages = defineMessages({
view: {
@@ -120,7 +121,7 @@ export const CollectionMenu: React.FC<{
const menu = useMemo(() => {
const viewCollectionItem: MenuItem = {
text: intl.formatMessage(messages.view),
- to: `/collections/${id}`,
+ to: getCollectionPath(id),
};
const shareItems: MenuItem[] = [
{
@@ -130,7 +131,7 @@ export const CollectionMenu: React.FC<{
{
text: intl.formatMessage(messages.copyLink),
action: () => {
- void navigator.clipboard.writeText(`/collections/${id}`);
+ void navigator.clipboard.writeText(getCollectionPath(id));
dispatch(showAlert({ message: messages.copyLinkConfirmation }));
},
},
diff --git a/app/javascript/mastodon/features/collections/editor/details.tsx b/app/javascript/mastodon/features/collections/editor/details.tsx
index fe8a17bb34..de568137e8 100644
--- a/app/javascript/mastodon/features/collections/editor/details.tsx
+++ b/app/javascript/mastodon/features/collections/editor/details.tsx
@@ -38,6 +38,8 @@ import {
} from 'mastodon/reducers/slices/collections';
import { useAppDispatch, useAppSelector } from 'mastodon/store';
+import { getCollectionPath } from '../utils';
+
import classes from './styles.module.scss';
import { WizardStepTitle } from './wizard_step_title';
@@ -134,7 +136,7 @@ export const CollectionDetails: React.FC = () => {
).then((result) => {
if (isFulfilled(result)) {
history.replace(`/@${currentUserName}/collections`);
- history.push(`/collections/${result.payload.collection.id}`, {
+ history.push(getCollectionPath(result.payload.collection.id), {
newCollection: true,
});
}
diff --git a/app/javascript/mastodon/features/collections/utils.ts b/app/javascript/mastodon/features/collections/utils.ts
index 60eb5133cb..1905edfef1 100644
--- a/app/javascript/mastodon/features/collections/utils.ts
+++ b/app/javascript/mastodon/features/collections/utils.ts
@@ -3,3 +3,5 @@ import { isServerFeatureEnabled } from '@/mastodon/utils/environment';
export function areCollectionsEnabled() {
return isServerFeatureEnabled('collections');
}
+
+export const getCollectionPath = (id: string) => `/collections/${id}`;
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.tsx b/app/javascript/mastodon/features/status/components/detailed_status.tsx
index b85841098a..ded57f02d0 100644
--- a/app/javascript/mastodon/features/status/components/detailed_status.tsx
+++ b/app/javascript/mastodon/features/status/components/detailed_status.tsx
@@ -29,9 +29,12 @@ import StatusContent from 'mastodon/components/status_content';
import { QuotedStatus } from 'mastodon/components/status_quoted';
import { VisibilityIcon } from 'mastodon/components/visibility_icon';
import { Audio } from 'mastodon/features/audio';
+import { CollectionPreviewCard } from 'mastodon/features/collections/components/collection_preview_card';
import scheduleIdleTask from 'mastodon/features/ui/util/schedule_idle_task';
import { Video } from 'mastodon/features/video';
import { useIdentity } from 'mastodon/identity_context';
+import type { CollectionAttachment } from 'mastodon/models/status';
+import { compareUrls } from 'mastodon/utils/compare_urls';
import Card from './card';
@@ -260,13 +263,25 @@ export const DetailedStatus: React.FC<{
);
}
} else if (status.get('card') && !status.get('quote')) {
- media = (
-
- );
+ const cardUrl: string = status.getIn(['card', 'url']);
+
+ const taggedCollection = status
+ .get('tagged_collections')
+ .find((item: CollectionAttachment) =>
+ compareUrls(item.get('url'), cardUrl),
+ );
+
+ if (taggedCollection) {
+ media =
;
+ } else {
+ media = (
+
+ );
+ }
}
if (status.get('application')) {
diff --git a/app/javascript/mastodon/models/status.ts b/app/javascript/mastodon/models/status.ts
index b043edb9ca..668546ea26 100644
--- a/app/javascript/mastodon/models/status.ts
+++ b/app/javascript/mastodon/models/status.ts
@@ -1,5 +1,6 @@
import type { RecordOf } from 'immutable';
+import type { ApiCollectionJSON } from 'mastodon/api_types/collections';
import type { ApiPreviewCardJSON } from 'mastodon/api_types/statuses';
export type { StatusVisibility } from 'mastodon/api_types/statuses';
@@ -10,3 +11,5 @@ export type Status = Immutable.Map
;
export type Card = RecordOf;
export type MediaAttachment = Immutable.Map;
+
+export type CollectionAttachment = RecordOf;
diff --git a/app/javascript/mastodon/utils/compare_urls.ts b/app/javascript/mastodon/utils/compare_urls.ts
new file mode 100644
index 0000000000..de4f6220e8
--- /dev/null
+++ b/app/javascript/mastodon/utils/compare_urls.ts
@@ -0,0 +1,14 @@
+export function compareUrls(href1: string, href2: string) {
+ try {
+ const url1 = new URL(href1);
+ const url2 = new URL(href2);
+
+ return (
+ url1.origin === url2.origin &&
+ url1.pathname === url2.pathname &&
+ url1.search === url2.search
+ );
+ } catch {
+ return false;
+ }
+}