diff --git a/app/javascript/mastodon/components/autosuggest/items.tsx b/app/javascript/mastodon/components/autosuggest/items.tsx
index 1e293f0454d..ffe286b10c1 100644
--- a/app/javascript/mastodon/components/autosuggest/items.tsx
+++ b/app/javascript/mastodon/components/autosuggest/items.tsx
@@ -2,8 +2,11 @@ import type React from 'react';
import classNames from 'classnames';
+import { SealCheckIcon } from '@phosphor-icons/react';
+
import { selectPlainAccount } from '@/mastodon/selectors/accounts';
import { useAppSelector } from '@/mastodon/store';
+import { urlToDomain } from '@/mastodon/utils/links';
import { Avatar } from '../avatar';
import { DisplayName } from '../display_name';
@@ -53,6 +56,10 @@ const AutosuggestAccount: React.FC<{ id: string }> = ({ id }) => {
return null;
}
+ const verifiedField = account.fields.find(
+ (field) => field.verified_at !== null,
+ );
+
return (
<>
@@ -61,7 +68,14 @@ const AutosuggestAccount: React.FC<{ id: string }> = ({ id }) => {
account={account}
variant='noDomain'
className={classes.itemAccountName}
- />
+ >
+ {verifiedField?.value_plain && (
+
+
+ {urlToDomain(verifiedField.value_plain)}
+
+ )}
+
{account.acct}
>
diff --git a/app/javascript/mastodon/components/autosuggest/styles.module.scss b/app/javascript/mastodon/components/autosuggest/styles.module.scss
index f70c3d0f7e0..cd3553caf31 100644
--- a/app/javascript/mastodon/components/autosuggest/styles.module.scss
+++ b/app/javascript/mastodon/components/autosuggest/styles.module.scss
@@ -52,6 +52,10 @@
.itemAccountName {
@include mixins.type-label-lg;
+
+ display: flex;
+ align-items: stretch;
+ gap: var(--space-2xs);
}
.itemAccountHandle {
@@ -59,3 +63,10 @@
color: var(--color-text-tertiary);
}
+
+.itemAccountVerified {
+ display: flex;
+ align-items: center;
+ color: var(--color-text-brand);
+ font-weight: normal;
+}
diff --git a/app/javascript/mastodon/features/compose/redesign/modal_cancel.tsx b/app/javascript/mastodon/features/compose/redesign/modal_cancel.tsx
index 0fa0eb7b0a1..88acdd2a7ab 100644
--- a/app/javascript/mastodon/features/compose/redesign/modal_cancel.tsx
+++ b/app/javascript/mastodon/features/compose/redesign/modal_cancel.tsx
@@ -14,7 +14,7 @@ import {
requestComposerFocus,
resetComposer,
} from '@/mastodon/reducers/slices/composer';
-import { useAppDispatch } from '@/mastodon/store';
+import { useAppDispatch, useAppSelector } from '@/mastodon/store';
const ComposerModalCancelConfirm: React.FC<{ openNew?: boolean }> = ({
openNew,
@@ -37,32 +37,62 @@ const ComposerModalCancelConfirm: React.FC<{ openNew?: boolean }> = ({
dispatch(requestComposerFocus());
}, [dispatch]);
+ const isEditing = useAppSelector((state) => !!state.compose.get('id'));
+
return (
-
+ {isEditing ? (
+
+ ) : (
+
+ )}
-
+ {isEditing ? (
+
+ ) : (
+
+ )}
diff --git a/app/javascript/mastodon/features/compose/redesign/styles.module.scss b/app/javascript/mastodon/features/compose/redesign/styles.module.scss
index 7bfefa108b4..1082406c02e 100644
--- a/app/javascript/mastodon/features/compose/redesign/styles.module.scss
+++ b/app/javascript/mastodon/features/compose/redesign/styles.module.scss
@@ -214,8 +214,22 @@ textarea.textarea {
// Reply
.reply {
- border-inline-start: 0.5px solid var(--color-border-primary);
- padding: 0 var(--space-md);
+ column-gap: var(--space-2xs);
+ display: grid;
+ grid-template-columns: auto 1fr;
+ grid-template-rows: auto auto;
+
+ &::before {
+ border-block-start: 2px solid var(--color-border-primary);
+ border-inline-start: 2px solid var(--color-border-primary);
+ border-top-left-radius: var(--radius-md);
+ box-sizing: border-box;
+ content: '';
+ display: block;
+ grid-row: span 2;
+ margin: var(--space-xs) var(--space-2xs) 0;
+ width: 20px;
+ }
a {
color: inherit;
diff --git a/app/javascript/mastodon/features/compose/redesign/visibility.tsx b/app/javascript/mastodon/features/compose/redesign/visibility.tsx
index 20e7e8c265d..c97cf21b47a 100644
--- a/app/javascript/mastodon/features/compose/redesign/visibility.tsx
+++ b/app/javascript/mastodon/features/compose/redesign/visibility.tsx
@@ -1,5 +1,4 @@
-import type React from 'react';
-import { useCallback } from 'react';
+import { useCallback, useState } from 'react';
import { FormattedMessage } from 'react-intl';
@@ -116,6 +115,11 @@ const ComposeVisibilityMenu: React.FC = () => {
const defaultQuotePolicy = useAppSelector(
(state) => state.compose.get('default_quote_policy') as ApiQuotePolicy,
);
+
+ // Track the last public quote policy, so the picker remembers what was last used before quoting was disabled.
+ const [lastQuotePolicy, setLastQuotePolicy] = useState(
+ defaultQuotePolicy !== 'nobody' ? defaultQuotePolicy : 'public',
+ );
const quotePolicy = currentQuotePolicy ?? defaultQuotePolicy;
const isReply = useAppSelector((state) => !!state.compose.get('in_reply_to'));
@@ -146,22 +150,23 @@ const ComposeVisibilityMenu: React.FC = () => {
switch (value) {
case 'public':
newQuotePolicy = 'public';
+ setLastQuotePolicy(newQuotePolicy);
break;
case 'followers':
newQuotePolicy = 'followers';
+ setLastQuotePolicy(newQuotePolicy);
break;
case 'others':
// If it's not checked, then it's nobody.
if (checked) {
// Only use the default if it's not nobody, as then it'll never be enabled.
- newQuotePolicy =
- defaultQuotePolicy !== 'nobody' ? defaultQuotePolicy : 'public';
+ newQuotePolicy = lastQuotePolicy;
}
break;
}
dispatch(setComposeQuotePolicy(newQuotePolicy));
},
- [defaultQuotePolicy, dispatch],
+ [dispatch, lastQuotePolicy],
);
const handleSwitchToMessage: React.MouseEventHandler =
diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json
index 252aabf865c..5f15c01a5a3 100644
--- a/app/javascript/mastodon/locales/en.json
+++ b/app/javascript/mastodon/locales/en.json
@@ -505,6 +505,10 @@
"compose.cancel_modal.body": "You have a draft already in progress. What would you like to do?",
"compose.cancel_modal.continue": "Continue draft",
"compose.cancel_modal.delete": "Delete draft",
+ "compose.cancel_modal.edit.body": "You were editing a post. What would you like to do?",
+ "compose.cancel_modal.edit.continue": "Continue editing",
+ "compose.cancel_modal.edit.delete": "Discard changes",
+ "compose.cancel_modal.edit.title": "Unsaved changes",
"compose.cancel_modal.title": "Discard draft",
"compose.counter": "{current, number}/{max, number}",
"compose.discoverable": "Discoverable in public feeds & search results",
diff --git a/app/javascript/mastodon/utils/links.ts b/app/javascript/mastodon/utils/links.ts
index 00821fa8d14..b1c53af6b33 100644
--- a/app/javascript/mastodon/utils/links.ts
+++ b/app/javascript/mastodon/utils/links.ts
@@ -10,6 +10,15 @@ export function setupLinkListeners() {
on('click', ':not(form) button[data-confirm]:not([form])', handleConfirmLink);
}
+export function urlToDomain(input: string | URL) {
+ try {
+ const url = new URL(input);
+ return url.hostname;
+ } catch {
+ return null;
+ }
+}
+
function handleConfirmLink(event: MouseEvent) {
const target = event.currentTarget;
if (