mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-14 08:19:05 +00:00
Merge commit '37ccffa95a30772b55e3f18d486d699ee6c5f9e8' into glitch-soc/merge-upstream
This commit is contained in:
@@ -1,9 +1,5 @@
|
||||
import Rails from '@rails/ujs';
|
||||
import { setupLinkListeners } from './utils/links';
|
||||
|
||||
export function start() {
|
||||
try {
|
||||
Rails.start();
|
||||
} catch {
|
||||
// If called twice
|
||||
}
|
||||
setupLinkListeners();
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ const renderHashtags = (hashtags: HashtagType[]) =>
|
||||
|
||||
const renderStatuses = (statusIds: string[]) =>
|
||||
hidePeek<string>(statusIds).map((id) => (
|
||||
<StatusQuoteManager key={id} id={id} />
|
||||
<StatusQuoteManager contextType='search' key={id} id={id} />
|
||||
));
|
||||
|
||||
type SearchType = 'all' | ApiSearchType;
|
||||
@@ -189,7 +189,7 @@ export const SearchResults: React.FC<{ multiColumn: boolean }> = ({
|
||||
onClickMore={handleSelectStatuses}
|
||||
>
|
||||
{results.statuses.slice(0, INITIAL_DISPLAY).map((id) => (
|
||||
<StatusQuoteManager key={id} id={id} />
|
||||
<StatusQuoteManager contextType='search' key={id} id={id} />
|
||||
))}
|
||||
</SearchSection>
|
||||
)}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import punycode from 'node:punycode';
|
||||
|
||||
import { useCallback, useId, useState } from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import punycode from 'punycode/';
|
||||
|
||||
import DescriptionIcon from '@/material-icons/400-24px/description-fill.svg?react';
|
||||
import OpenInNewIcon from '@/material-icons/400-24px/open_in_new.svg?react';
|
||||
import PlayArrowIcon from '@/material-icons/400-24px/play_arrow-fill.svg?react';
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { initialState } from '@/mastodon/initial_state';
|
||||
|
||||
interface FocusColumnOptions {
|
||||
index?: number;
|
||||
focusItem?: 'first' | 'first-visible';
|
||||
@@ -14,7 +12,10 @@ export function focusColumn({
|
||||
focusItem = 'first',
|
||||
}: FocusColumnOptions = {}) {
|
||||
// Skip the leftmost drawer in multi-column mode
|
||||
const indexOffset = initialState?.meta.advanced_layout ? 1 : 0;
|
||||
const isMultiColumnLayout = !!document.querySelector(
|
||||
'body.layout-multiple-columns',
|
||||
);
|
||||
const indexOffset = isMultiColumnLayout ? 1 : 0;
|
||||
|
||||
const column = document.querySelector(
|
||||
`.column:nth-child(${index + indexOffset})`,
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
"account.disable_notifications": "@{name}さんの投稿時の通知を停止",
|
||||
"account.domain_blocking": "ブロックしているドメイン",
|
||||
"account.edit_profile": "プロフィール編集",
|
||||
"account.edit_profile_short": "編集",
|
||||
"account.enable_notifications": "@{name}さんの投稿時に通知",
|
||||
"account.endorse": "プロフィールで紹介する",
|
||||
"account.familiar_followers_many": "{name1}、{name2}、他{othersCount, plural, one {one other you know} other {# others you know}}人のユーザーにフォローされています",
|
||||
@@ -172,6 +173,8 @@
|
||||
"column.edit_list": "リストを編集",
|
||||
"column.favourites": "お気に入り",
|
||||
"column.firehose": "リアルタイムフィード",
|
||||
"column.firehose_local": "このサーバーのリアルタイムフィード",
|
||||
"column.firehose_singular": "リアルタイムフィード",
|
||||
"column.follow_requests": "フォローリクエスト",
|
||||
"column.home": "ホーム",
|
||||
"column.list_members": "リストのメンバーを管理",
|
||||
@@ -251,6 +254,7 @@
|
||||
"confirmations.remove_from_followers.message": "{name}さんはあなたをフォローしなくなります。本当によろしいですか?",
|
||||
"confirmations.remove_from_followers.title": "フォロワーを削除しますか?",
|
||||
"confirmations.revoke_quote.confirm": "投稿を削除",
|
||||
"confirmations.revoke_quote.message": "この操作は元に戻せません。",
|
||||
"confirmations.revoke_quote.title": "投稿を削除しますか?",
|
||||
"confirmations.unblock.confirm": "ブロック解除",
|
||||
"confirmations.unblock.title": "@{name}さんのブロックを解除しますか?",
|
||||
@@ -477,6 +481,7 @@
|
||||
"keyboard_shortcuts.home": "ホームタイムラインを開く",
|
||||
"keyboard_shortcuts.hotkey": "ホットキー",
|
||||
"keyboard_shortcuts.legend": "この一覧を表示",
|
||||
"keyboard_shortcuts.load_more": "「もっと見る」ボタンに移動",
|
||||
"keyboard_shortcuts.local": "ローカルタイムラインを開く",
|
||||
"keyboard_shortcuts.mention": "メンション",
|
||||
"keyboard_shortcuts.muted": "ミュートしたユーザーのリストを開く",
|
||||
@@ -497,6 +502,7 @@
|
||||
"keyboard_shortcuts.translate": "投稿を翻訳する",
|
||||
"keyboard_shortcuts.unfocus": "投稿の入力欄・検索欄から離れる",
|
||||
"keyboard_shortcuts.up": "カラム内一つ上に移動",
|
||||
"learn_more_link.got_it": "了解",
|
||||
"learn_more_link.learn_more": "もっと見る",
|
||||
"lightbox.close": "閉じる",
|
||||
"lightbox.next": "次",
|
||||
@@ -611,6 +617,7 @@
|
||||
"notification.moderation_warning.action_suspend": "あなたのアカウントは停止されました。",
|
||||
"notification.own_poll": "アンケートが終了しました",
|
||||
"notification.poll": "投票したアンケートが終了しました",
|
||||
"notification.quoted_update": "あなたが引用した投稿を {name} が編集しました",
|
||||
"notification.reblog": "{name}さんがあなたの投稿をブーストしました",
|
||||
"notification.reblog.name_and_others_with_link": "{name}さんと<a>ほか{count, plural, other {#人}}</a>がブーストしました",
|
||||
"notification.relationships_severance_event": "{name} との関係が失われました",
|
||||
@@ -753,6 +760,7 @@
|
||||
"relative_time.minutes": "{number}分前",
|
||||
"relative_time.seconds": "{number}秒前",
|
||||
"relative_time.today": "今日",
|
||||
"remove_quote_hint.button_label": "了解",
|
||||
"reply_indicator.attachments": "{count, plural, other {#件のメディア}}",
|
||||
"reply_indicator.cancel": "キャンセル",
|
||||
"reply_indicator.poll": "アンケート",
|
||||
|
||||
@@ -14,7 +14,7 @@ const getStatusInputSelectors = [
|
||||
(state, { id }) => state.getIn(['accounts', state.getIn(['statuses', id, 'account'])]),
|
||||
(state, { id }) => state.getIn(['accounts', state.getIn(['statuses', state.getIn(['statuses', id, 'reblog']), 'account'])]),
|
||||
getFilters,
|
||||
(_, { contextType }) => ['detailed', 'bookmarks', 'favourites'].includes(contextType),
|
||||
(_, { contextType }) => ['detailed', 'bookmarks', 'favourites', 'search'].includes(contextType),
|
||||
];
|
||||
|
||||
function getStatusResultFunction(
|
||||
|
||||
88
app/javascript/mastodon/utils/links.ts
Normal file
88
app/javascript/mastodon/utils/links.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { on } from 'delegated-events';
|
||||
|
||||
export function setupLinkListeners() {
|
||||
on('click', 'a[data-confirm]', handleConfirmLink);
|
||||
|
||||
// We don't want to target links with data-confirm here, as those are handled already.
|
||||
on('click', 'a[data-method]:not([data-confirm])', handleMethodLink);
|
||||
}
|
||||
|
||||
function handleConfirmLink(event: MouseEvent) {
|
||||
const anchor = event.currentTarget;
|
||||
if (!(anchor instanceof HTMLAnchorElement)) {
|
||||
return;
|
||||
}
|
||||
const message = anchor.dataset.confirm;
|
||||
if (!message || !window.confirm(message)) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
if (anchor.dataset.method) {
|
||||
handleMethodLink(event);
|
||||
}
|
||||
}
|
||||
|
||||
function handleMethodLink(event: MouseEvent) {
|
||||
const anchor = event.currentTarget;
|
||||
if (!(anchor instanceof HTMLAnchorElement)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const method = anchor.dataset.method?.toLowerCase();
|
||||
if (!method) {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
|
||||
// Create and submit a form with the specified method.
|
||||
const form = document.createElement('form');
|
||||
form.method = 'post';
|
||||
form.action = anchor.href;
|
||||
|
||||
// Add the hidden _method input to simulate other HTTP methods.
|
||||
const methodInput = document.createElement('input');
|
||||
methodInput.type = 'hidden';
|
||||
methodInput.name = '_method';
|
||||
methodInput.value = method;
|
||||
form.appendChild(methodInput);
|
||||
|
||||
// Add CSRF token if available for same-origin requests.
|
||||
const csrf = getCSRFToken();
|
||||
if (csrf && !isCrossDomain(anchor.href)) {
|
||||
const csrfInput = document.createElement('input');
|
||||
csrfInput.type = 'hidden';
|
||||
csrfInput.name = csrf.param;
|
||||
csrfInput.value = csrf.token;
|
||||
form.appendChild(csrfInput);
|
||||
}
|
||||
|
||||
// The form needs to be in the document to be submitted.
|
||||
form.style.display = 'none';
|
||||
document.body.appendChild(form);
|
||||
|
||||
// We use requestSubmit to ensure any form submit handlers are properly invoked.
|
||||
form.requestSubmit();
|
||||
}
|
||||
|
||||
function getCSRFToken() {
|
||||
const param = document.querySelector<HTMLMetaElement>(
|
||||
'meta[name="csrf-param"]',
|
||||
);
|
||||
const token = document.querySelector<HTMLMetaElement>(
|
||||
'meta[name="csrf-token"]',
|
||||
);
|
||||
if (param && token) {
|
||||
return { param: param.content, token: token.content };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function isCrossDomain(href: string) {
|
||||
const link = document.createElement('a');
|
||||
link.href = href;
|
||||
return (
|
||||
link.protocol !== window.location.protocol ||
|
||||
link.host !== window.location.host
|
||||
);
|
||||
}
|
||||
@@ -6204,12 +6204,14 @@ a.status-card {
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
align-items: center;
|
||||
justify-content: space-around; // If set to center, the fullscreen image overlay is misaligned.
|
||||
|
||||
> div {
|
||||
flex-shrink: 0;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7373,6 +7375,13 @@ a.status-card {
|
||||
grid-template-rows: 1fr 1fr;
|
||||
gap: 2px;
|
||||
|
||||
&--layout-1 {
|
||||
// The size of single images is determined by their
|
||||
// aspect-ratio, applied via inline style attribute
|
||||
width: initial;
|
||||
max-height: 460px;
|
||||
}
|
||||
|
||||
&--layout-2 {
|
||||
& > .media-gallery__item:nth-child(1) {
|
||||
border-end-end-radius: 0;
|
||||
@@ -7698,14 +7707,11 @@ a.status-card {
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
background: $base-shadow-color;
|
||||
max-width: 100%;
|
||||
max-height: max(400px, 60vh);
|
||||
margin-inline: auto;
|
||||
max-height: 460px;
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
color: $white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
outline: 1px solid var(--media-outline-color);
|
||||
outline-offset: -1px;
|
||||
z-index: 2;
|
||||
|
||||
@@ -113,8 +113,8 @@
|
||||
}
|
||||
|
||||
.current {
|
||||
color: var(--color-bg-inverted);
|
||||
background: var(--color-text-on-inverted);
|
||||
color: var(--color-bg-primary);
|
||||
background: var(--color-text-primary);
|
||||
border-radius: 100px;
|
||||
cursor: default;
|
||||
margin: 0 10px;
|
||||
|
||||
@@ -6085,12 +6085,14 @@ a.status-card {
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
align-items: center;
|
||||
justify-content: space-around; // If set to center, the fullscreen image overlay is misaligned.
|
||||
|
||||
> div {
|
||||
flex-shrink: 0;
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7159,6 +7161,13 @@ a.status-card {
|
||||
grid-template-rows: 1fr 1fr;
|
||||
gap: 2px;
|
||||
|
||||
&--layout-1 {
|
||||
// The size of single images is determined by their
|
||||
// aspect-ratio, applied via inline style attribute
|
||||
width: initial;
|
||||
max-height: 460px;
|
||||
}
|
||||
|
||||
&--layout-2 {
|
||||
& > .media-gallery__item:nth-child(1) {
|
||||
border-end-end-radius: 0;
|
||||
@@ -7491,13 +7500,10 @@ a.status-card {
|
||||
position: relative;
|
||||
color: var(--color-text-on-media);
|
||||
background: var(--color-bg-media);
|
||||
max-width: 100%;
|
||||
max-height: max(400px, 60vh);
|
||||
margin-inline: auto;
|
||||
max-height: 460px;
|
||||
border-radius: 8px;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
outline: 1px solid var(--color-border-media);
|
||||
outline-offset: -1px;
|
||||
z-index: 2;
|
||||
|
||||
Reference in New Issue
Block a user