mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-18 02:28:08 +00:00
Merge commit '0219b7cad7d9ef800f82cc561571b70da040433f' into glitch-soc/merge-upstream
This commit is contained in:
@@ -6,6 +6,9 @@ module AsyncRefreshesConcern
|
|||||||
def add_async_refresh_header(async_refresh, retry_seconds: 3)
|
def add_async_refresh_header(async_refresh, retry_seconds: 3)
|
||||||
return unless async_refresh.running?
|
return unless async_refresh.running?
|
||||||
|
|
||||||
response.headers['Mastodon-Async-Refresh'] = "id=\"#{async_refresh.id}\", retry=#{retry_seconds}"
|
value = "id=\"#{async_refresh.id}\", retry=#{retry_seconds}"
|
||||||
|
value += ", result_count=#{async_refresh.result_count}" unless async_refresh.result_count.nil?
|
||||||
|
|
||||||
|
response.headers['Mastodon-Async-Refresh'] = value
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -57,6 +57,20 @@ module StatusesHelper
|
|||||||
components.compact_blank.join("\n\n")
|
components.compact_blank.join("\n\n")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# This logic should be kept in sync with https://github.com/mastodon/mastodon/blob/425311e1d95c8a64ddac6c724fca247b8b893a82/app/javascript/mastodon/features/status/components/card.jsx#L160
|
||||||
|
def preview_card_aspect_ratio_classname(preview_card)
|
||||||
|
interactive = preview_card.type == 'video'
|
||||||
|
large_image = (preview_card.image.present? && preview_card.width > preview_card.height) || interactive
|
||||||
|
|
||||||
|
if large_image && interactive
|
||||||
|
'status-card__image--video'
|
||||||
|
elsif large_image
|
||||||
|
'status-card__image--large'
|
||||||
|
else
|
||||||
|
'status-card__image--normal'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def visibility_icon(status)
|
def visibility_icon(status)
|
||||||
VISIBLITY_ICONS[status.visibility.to_sym]
|
VISIBLITY_ICONS[status.visibility.to_sym]
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
|
|
||||||
import Rails from '@rails/ujs';
|
import Rails from '@rails/ujs';
|
||||||
|
import { decode, ValidationError } from 'blurhash';
|
||||||
|
|
||||||
import ready from '../mastodon/ready';
|
import ready from '../mastodon/ready';
|
||||||
|
|
||||||
@@ -362,6 +363,46 @@ ready(() => {
|
|||||||
document.querySelectorAll('[data-admin-component]').forEach((element) => {
|
document.querySelectorAll('[data-admin-component]').forEach((element) => {
|
||||||
void mountReactComponent(element);
|
void mountReactComponent(element);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll<HTMLCanvasElement>('canvas[data-blurhash]')
|
||||||
|
.forEach((canvas) => {
|
||||||
|
const blurhash = canvas.dataset.blurhash;
|
||||||
|
if (blurhash) {
|
||||||
|
try {
|
||||||
|
// decode returns a Uint8ClampedArray<ArrayBufferLike> not Uint8ClampedArray<ArrayBuffer>
|
||||||
|
const pixels = decode(
|
||||||
|
blurhash,
|
||||||
|
32,
|
||||||
|
32,
|
||||||
|
) as Uint8ClampedArray<ArrayBuffer>;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
const imageData = new ImageData(pixels, 32, 32);
|
||||||
|
|
||||||
|
ctx?.putImageData(imageData, 0, 0);
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof ValidationError) {
|
||||||
|
// ignore blurhash validation errors
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document
|
||||||
|
.querySelectorAll<HTMLDivElement>('.preview-card')
|
||||||
|
.forEach((previewCard) => {
|
||||||
|
const spoilerButton = previewCard.querySelector('.spoiler-button');
|
||||||
|
if (!spoilerButton) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spoilerButton.addEventListener('click', () => {
|
||||||
|
previewCard.classList.toggle('preview-card--image-visible');
|
||||||
|
});
|
||||||
|
});
|
||||||
}).catch((reason: unknown) => {
|
}).catch((reason: unknown) => {
|
||||||
throw reason;
|
throw reason;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -40,6 +40,9 @@
|
|||||||
"account.featured_tags.last_status_never": "Embann ebet",
|
"account.featured_tags.last_status_never": "Embann ebet",
|
||||||
"account.follow": "Heuliañ",
|
"account.follow": "Heuliañ",
|
||||||
"account.follow_back": "Heuliañ d'ho tro",
|
"account.follow_back": "Heuliañ d'ho tro",
|
||||||
|
"account.follow_back_short": "Heuliañ d'ho tro",
|
||||||
|
"account.follow_request": "Reked d'ho heuliañ",
|
||||||
|
"account.follow_request_cancel": "Nullañ ar reked",
|
||||||
"account.follow_request_cancel_short": "Nullañ",
|
"account.follow_request_cancel_short": "Nullañ",
|
||||||
"account.followers": "Tud koumanantet",
|
"account.followers": "Tud koumanantet",
|
||||||
"account.followers.empty": "Den na heul an implijer·ez-mañ c'hoazh.",
|
"account.followers.empty": "Den na heul an implijer·ez-mañ c'hoazh.",
|
||||||
@@ -212,6 +215,7 @@
|
|||||||
"confirmations.missing_alt_text.secondary": "Embann memes tra",
|
"confirmations.missing_alt_text.secondary": "Embann memes tra",
|
||||||
"confirmations.missing_alt_text.title": "Ouzhpennañ an eiltestenn?",
|
"confirmations.missing_alt_text.title": "Ouzhpennañ an eiltestenn?",
|
||||||
"confirmations.mute.confirm": "Kuzhat",
|
"confirmations.mute.confirm": "Kuzhat",
|
||||||
|
"confirmations.quiet_post_quote_info.got_it": "Mat eo",
|
||||||
"confirmations.redraft.confirm": "Diverkañ ha skrivañ en-dro",
|
"confirmations.redraft.confirm": "Diverkañ ha skrivañ en-dro",
|
||||||
"confirmations.redraft.title": "Diverkañ ha skrivañ an embann en-dro?",
|
"confirmations.redraft.title": "Diverkañ ha skrivañ an embann en-dro?",
|
||||||
"confirmations.remove_from_followers.confirm": "Dilemel an heulier·ez",
|
"confirmations.remove_from_followers.confirm": "Dilemel an heulier·ez",
|
||||||
@@ -246,6 +250,7 @@
|
|||||||
"domain_block_modal.block_account_instead": "Stankañ @{name} kentoc'h",
|
"domain_block_modal.block_account_instead": "Stankañ @{name} kentoc'h",
|
||||||
"domain_block_modal.title": "Stankañ an domani?",
|
"domain_block_modal.title": "Stankañ an domani?",
|
||||||
"domain_pill.server": "Dafariad",
|
"domain_pill.server": "Dafariad",
|
||||||
|
"domain_pill.their_handle": "H·ec'h anaouder:",
|
||||||
"domain_pill.username": "Anv-implijer",
|
"domain_pill.username": "Anv-implijer",
|
||||||
"domain_pill.whats_in_a_handle": "Petra eo an anaouder?",
|
"domain_pill.whats_in_a_handle": "Petra eo an anaouder?",
|
||||||
"domain_pill.your_handle": "Hoc'h anaouder:",
|
"domain_pill.your_handle": "Hoc'h anaouder:",
|
||||||
@@ -267,6 +272,7 @@
|
|||||||
"emoji_button.search_results": "Disoc'hoù an enklask",
|
"emoji_button.search_results": "Disoc'hoù an enklask",
|
||||||
"emoji_button.symbols": "Arouezioù",
|
"emoji_button.symbols": "Arouezioù",
|
||||||
"emoji_button.travel": "Beajiñ & Lec'hioù",
|
"emoji_button.travel": "Beajiñ & Lec'hioù",
|
||||||
|
"empty_column.account_featured_other.unknown": "N'eo ket bet lakaet netra en a-raok gant ar gont-mañ.",
|
||||||
"empty_column.account_suspended": "Kont astalet",
|
"empty_column.account_suspended": "Kont astalet",
|
||||||
"empty_column.account_timeline": "Embannadur ebet amañ!",
|
"empty_column.account_timeline": "Embannadur ebet amañ!",
|
||||||
"empty_column.account_unavailable": "Profil dihegerz",
|
"empty_column.account_unavailable": "Profil dihegerz",
|
||||||
@@ -493,6 +499,7 @@
|
|||||||
"notifications.column_settings.admin.sign_up": "Enskrivadurioù nevez :",
|
"notifications.column_settings.admin.sign_up": "Enskrivadurioù nevez :",
|
||||||
"notifications.column_settings.alert": "Kemennoù war ar burev",
|
"notifications.column_settings.alert": "Kemennoù war ar burev",
|
||||||
"notifications.column_settings.favourite": "Muiañ-karet:",
|
"notifications.column_settings.favourite": "Muiañ-karet:",
|
||||||
|
"notifications.column_settings.filter_bar.advanced": "Diskouez an holl rummadoù",
|
||||||
"notifications.column_settings.follow": "Heulierien nevez:",
|
"notifications.column_settings.follow": "Heulierien nevez:",
|
||||||
"notifications.column_settings.follow_request": "Rekedoù heuliañ nevez:",
|
"notifications.column_settings.follow_request": "Rekedoù heuliañ nevez:",
|
||||||
"notifications.column_settings.group": "Strollañ",
|
"notifications.column_settings.group": "Strollañ",
|
||||||
@@ -518,7 +525,7 @@
|
|||||||
"notifications.group": "{count} a gemennoù",
|
"notifications.group": "{count} a gemennoù",
|
||||||
"notifications.mark_as_read": "Merkañ an holl kemennoù evel bezañ lennet",
|
"notifications.mark_as_read": "Merkañ an holl kemennoù evel bezañ lennet",
|
||||||
"notifications.permission_denied": "Kemennoù war ar burev n'int ket hegerz rak pedadenn aotren ar merdeer a zo bet nullet araok",
|
"notifications.permission_denied": "Kemennoù war ar burev n'int ket hegerz rak pedadenn aotren ar merdeer a zo bet nullet araok",
|
||||||
"notifications.permission_denied_alert": "Kemennoù wa ar burev na c'hellont ket bezañ lezelet, rak aotre ar merdeer a zo bet nac'het a-raok",
|
"notifications.permission_denied_alert": "Kemennoù war ar burev na c'hellont ket bezañ lezelet, rak aotre ar merdeer a zo bet nac'het a-raok",
|
||||||
"notifications.permission_required": "Kemennoù war ar burev n'int ket hegerz abalamour d'an aotre rekis n'eo ket bet roet.",
|
"notifications.permission_required": "Kemennoù war ar burev n'int ket hegerz abalamour d'an aotre rekis n'eo ket bet roet.",
|
||||||
"notifications.policy.accept": "Asantiñ",
|
"notifications.policy.accept": "Asantiñ",
|
||||||
"notifications.policy.accept_hint": "Diskouez er c’hemennoù",
|
"notifications.policy.accept_hint": "Diskouez er c’hemennoù",
|
||||||
|
|||||||
@@ -1962,7 +1962,6 @@ a.sparkline {
|
|||||||
.status__card {
|
.status__card {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background: $ui-base-color;
|
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
@@ -1981,8 +1980,105 @@ a.sparkline {
|
|||||||
.status__content {
|
.status__content {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
|
|
||||||
summary {
|
> details {
|
||||||
display: list-item;
|
summary {
|
||||||
|
display: block;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: var(--nested-card-background);
|
||||||
|
color: var(--nested-card-text);
|
||||||
|
border: var(--nested-card-border);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 8px 13px;
|
||||||
|
position: relative;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 22px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: attr(data-show, 'Show more');
|
||||||
|
margin-top: 8px;
|
||||||
|
display: block;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 20px;
|
||||||
|
color: $highlight-text-color;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
padding: 0;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus-visible {
|
||||||
|
&::after {
|
||||||
|
text-decoration: underline !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&[open] summary {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: attr(data-hide, 'Hide post');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.preview-card {
|
||||||
|
position: relative;
|
||||||
|
max-width: 566px;
|
||||||
|
|
||||||
|
.status-card__image {
|
||||||
|
&--video {
|
||||||
|
aspect-ratio: 16 / 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--large {
|
||||||
|
aspect-ratio: 1.91 / 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
aspect-ratio: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spoiler-button__overlay__label {
|
||||||
|
outline: 1px solid var(--media-outline-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hide-button {
|
||||||
|
// Toggled to appear when the preview-card is unblurred:
|
||||||
|
display: none;
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
right: 5px;
|
||||||
|
color: $white;
|
||||||
|
border: 0;
|
||||||
|
outline: 1px solid var(--media-outline-color);
|
||||||
|
background-color: color.change($black, $alpha: 0.45);
|
||||||
|
backdrop-filter: $backdrop-blur-filter;
|
||||||
|
padding: 3px 12px;
|
||||||
|
border-radius: 99px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 20px;
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background-color: color.change($black, $alpha: 0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.preview-card--image-visible {
|
||||||
|
.hide-button {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spoiler-button__overlay,
|
||||||
|
.status-card__image-preview {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,10 @@ class StatusEdit < ApplicationRecord
|
|||||||
underlying_quote
|
underlying_quote
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_preview_card?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
def with_media?
|
def with_media?
|
||||||
ordered_media_attachments.any?
|
ordered_media_attachments.any?
|
||||||
end
|
end
|
||||||
|
|||||||
30
app/views/admin/shared/_preview_card.html.haml
Normal file
30
app/views/admin/shared/_preview_card.html.haml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
/# locals: (preview_card:)
|
||||||
|
|
||||||
|
.preview-card
|
||||||
|
.status-card.expanded
|
||||||
|
.status-card__image{ class: preview_card_aspect_ratio_classname(preview_card) }
|
||||||
|
.spoiler-button
|
||||||
|
%button.hide-button{ type: 'button' }= t('link_preview.potentially_sensitive_content.hide_button')
|
||||||
|
%button.spoiler-button__overlay{ type: 'button' }
|
||||||
|
%span.spoiler-button__overlay__label
|
||||||
|
%span= t('link_preview.potentially_sensitive_content.label')
|
||||||
|
%span.spoiler-button__overlay__action
|
||||||
|
%span= t('link_preview.potentially_sensitive_content.action')
|
||||||
|
%canvas.status-card__image-preview{ 'data-blurhash': preview_card.blurhash, width: 32, height: 32 }
|
||||||
|
= image_tag preview_card.image.url, alt: '', class: 'status-card__image-image'
|
||||||
|
= link_to preview_card.url, target: '_blank', rel: 'noopener', data: { confirm: t('link_preview.potentially_sensitive_content.confirm_visit') } do
|
||||||
|
.status-card__content{ dir: 'auto' }
|
||||||
|
%span.status-card__host
|
||||||
|
%span{ lang: preview_card.language }
|
||||||
|
= preview_card.provider_name
|
||||||
|
- if preview_card.published_at
|
||||||
|
·
|
||||||
|
%time.relative-formatted{ datetime: preview_card.published_at.iso8601, title: l(preview_card.published_at) }= l(preview_card.published_at)
|
||||||
|
%strong.status-card__title{ title: preview_card.title, lang: preview_card.language }
|
||||||
|
= preview_card.title
|
||||||
|
- if preview_card.author_name.present?
|
||||||
|
%span.status-card__author
|
||||||
|
= t('link_preview.author_html', name: content_tag(:strong, preview_card.author_name))
|
||||||
|
- else
|
||||||
|
%span.status-card__description{ lang: preview_card.language }
|
||||||
|
= preview_card.description
|
||||||
@@ -13,6 +13,9 @@
|
|||||||
%button.button.button-secondary{ disabled: true }
|
%button.button.button-secondary{ disabled: true }
|
||||||
= t('polls.vote')
|
= t('polls.vote')
|
||||||
|
|
||||||
|
- if status.with_preview_card?
|
||||||
|
= render partial: 'admin/shared/preview_card', locals: { preview_card: status.preview_card }
|
||||||
|
|
||||||
- if status.with_media?
|
- if status.with_media?
|
||||||
- if status.ordered_media_attachments.first.video?
|
- if status.ordered_media_attachments.first.video?
|
||||||
= render_video_component(status, visible: false)
|
= render_video_component(status, visible: false)
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
.status__content><
|
.status__content><
|
||||||
- if status.spoiler_text.present?
|
- if status.spoiler_text.present?
|
||||||
%details<
|
%details<
|
||||||
%summary><
|
%summary{
|
||||||
%strong> Content warning: #{prerender_custom_emojis(h(status.spoiler_text), status.emojis)}
|
data: {
|
||||||
|
show: t('statuses.content_warnings.show'),
|
||||||
|
hide: t('statuses.content_warnings.hide'),
|
||||||
|
}
|
||||||
|
}><
|
||||||
|
%strong>
|
||||||
|
= prerender_custom_emojis(h(status.spoiler_text), status.emojis)
|
||||||
= prerender_custom_emojis(status_content_format(status), status.emojis)
|
= prerender_custom_emojis(status_content_format(status), status.emojis)
|
||||||
= render partial: 'admin/shared/status_attachments', locals: { status: status.proper }
|
= render partial: 'admin/shared/status_attachments', locals: { status: status.proper }
|
||||||
- else
|
- else
|
||||||
|
|||||||
@@ -373,6 +373,7 @@ br:
|
|||||||
manage_rules: Merañ reolennoù ar servijer
|
manage_rules: Merañ reolennoù ar servijer
|
||||||
title: Diwar-benn
|
title: Diwar-benn
|
||||||
appearance:
|
appearance:
|
||||||
|
preamble: Personelaat etrefas web Mastodon.
|
||||||
title: Neuz
|
title: Neuz
|
||||||
content_retention:
|
content_retention:
|
||||||
danger_zone: Takad dañjer
|
danger_zone: Takad dañjer
|
||||||
@@ -777,12 +778,13 @@ br:
|
|||||||
account: Kont
|
account: Kont
|
||||||
account_settings: Arventennoù ar gont
|
account_settings: Arventennoù ar gont
|
||||||
aliases: Aliasoù ar gont
|
aliases: Aliasoù ar gont
|
||||||
|
appearance: Neuz
|
||||||
back: Distreiñ da vMastodon
|
back: Distreiñ da vMastodon
|
||||||
delete: Dilemel ar gont
|
delete: Dilemel ar gont
|
||||||
development: Diorren
|
development: Diorren
|
||||||
edit_profile: Kemmañ ar profil
|
edit_profile: Kemmañ ar profil
|
||||||
export: Ezporzhiañ
|
export: Ezporzhiañ
|
||||||
featured_tags: Gerioù-klik en a-raok
|
featured_tags: Penngerioù-klik
|
||||||
import: Enporzhiañ
|
import: Enporzhiañ
|
||||||
import_and_export: Enporzhiañ hag ezporzhiañ
|
import_and_export: Enporzhiañ hag ezporzhiañ
|
||||||
notifications: Kemennoù dre bostel
|
notifications: Kemennoù dre bostel
|
||||||
|
|||||||
@@ -1591,6 +1591,13 @@ en:
|
|||||||
expires_at: Expires
|
expires_at: Expires
|
||||||
uses: Uses
|
uses: Uses
|
||||||
title: Invite people
|
title: Invite people
|
||||||
|
link_preview:
|
||||||
|
author_html: By %{name}
|
||||||
|
potentially_sensitive_content:
|
||||||
|
action: Click to show
|
||||||
|
confirm_visit: Are you sure you wish to open this link?
|
||||||
|
hide_button: Hide
|
||||||
|
label: Potentially sensitive content
|
||||||
lists:
|
lists:
|
||||||
errors:
|
errors:
|
||||||
limit: You have reached the maximum number of lists
|
limit: You have reached the maximum number of lists
|
||||||
@@ -1902,6 +1909,9 @@ en:
|
|||||||
other: "%{count} videos"
|
other: "%{count} videos"
|
||||||
boosted_from_html: Boosted from %{acct_link}
|
boosted_from_html: Boosted from %{acct_link}
|
||||||
content_warning: 'Content warning: %{warning}'
|
content_warning: 'Content warning: %{warning}'
|
||||||
|
content_warnings:
|
||||||
|
hide: Hide post
|
||||||
|
show: Show more
|
||||||
default_language: Same as interface language
|
default_language: Same as interface language
|
||||||
disallowed_hashtags:
|
disallowed_hashtags:
|
||||||
one: 'contained a disallowed hashtag: %{tags}'
|
one: 'contained a disallowed hashtag: %{tags}'
|
||||||
|
|||||||
Reference in New Issue
Block a user