mirror of
https://github.com/glitch-soc/mastodon.git
synced 2025-12-18 10:37:45 +00:00
Merge commit '3b52dca4057560c58b260433722d91650fcd5040' into glitch-soc/merge-upstream
Conflicts: - `app/serializers/initial_state_serializer.rb`: Upstream added a `features` attribute where glitch-soc had extra ones. Added `features` like upstream did.
This commit is contained in:
@@ -1,12 +1,30 @@
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { useLinks } from 'mastodon/hooks/useLinks';
|
||||
|
||||
export const AccountBio: React.FC<{
|
||||
interface AccountBioProps {
|
||||
note: string;
|
||||
className: string;
|
||||
}> = ({ note, className }) => {
|
||||
const handleClick = useLinks();
|
||||
dropdownAccountId?: string;
|
||||
}
|
||||
|
||||
if (note.length === 0 || note === '<p></p>') {
|
||||
export const AccountBio: React.FC<AccountBioProps> = ({
|
||||
note,
|
||||
className,
|
||||
dropdownAccountId,
|
||||
}) => {
|
||||
const handleClick = useLinks(!!dropdownAccountId);
|
||||
const handleNodeChange = useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
if (!dropdownAccountId || !node || node.childNodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
addDropdownToHashtags(node, dropdownAccountId);
|
||||
},
|
||||
[dropdownAccountId],
|
||||
);
|
||||
|
||||
if (note.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -15,6 +33,28 @@ export const AccountBio: React.FC<{
|
||||
className={`${className} translate`}
|
||||
dangerouslySetInnerHTML={{ __html: note }}
|
||||
onClickCapture={handleClick}
|
||||
ref={handleNodeChange}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
function addDropdownToHashtags(node: HTMLElement | null, accountId: string) {
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
for (const childNode of node.childNodes) {
|
||||
if (!(childNode instanceof HTMLElement)) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
childNode instanceof HTMLAnchorElement &&
|
||||
(childNode.classList.contains('hashtag') ||
|
||||
childNode.innerText.startsWith('#')) &&
|
||||
!childNode.dataset.menuHashtag
|
||||
) {
|
||||
childNode.dataset.menuHashtag = accountId;
|
||||
} else if (childNode.childNodes.length > 0) {
|
||||
addDropdownToHashtags(childNode, accountId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import classNames from 'classnames';
|
||||
import { Helmet } from 'react-helmet';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
|
||||
import { AccountBio } from '@/mastodon/components/account_bio';
|
||||
import CheckIcon from '@/material-icons/400-24px/check.svg?react';
|
||||
import LockIcon from '@/material-icons/400-24px/lock.svg?react';
|
||||
import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||
@@ -773,7 +774,6 @@ export const AccountHeader: React.FC<{
|
||||
);
|
||||
}
|
||||
|
||||
const content = { __html: account.note_emojified };
|
||||
const displayNameHtml = { __html: account.display_name_html };
|
||||
const fields = account.fields;
|
||||
const isLocal = !account.acct.includes('@');
|
||||
@@ -897,12 +897,11 @@ export const AccountHeader: React.FC<{
|
||||
<AccountNote accountId={accountId} />
|
||||
)}
|
||||
|
||||
{account.note.length > 0 && account.note !== '<p></p>' && (
|
||||
<div
|
||||
className='account__header__content translate'
|
||||
dangerouslySetInnerHTML={content}
|
||||
/>
|
||||
)}
|
||||
<AccountBio
|
||||
note={account.note_emojified}
|
||||
dropdownAccountId={accountId}
|
||||
className='account__header__content'
|
||||
/>
|
||||
|
||||
<div className='account__header__fields'>
|
||||
<dl>
|
||||
|
||||
@@ -8,13 +8,14 @@ import { openURL } from 'mastodon/actions/search';
|
||||
import { useAppDispatch } from 'mastodon/store';
|
||||
|
||||
const isMentionClick = (element: HTMLAnchorElement) =>
|
||||
element.classList.contains('mention');
|
||||
element.classList.contains('mention') &&
|
||||
!element.classList.contains('hashtag');
|
||||
|
||||
const isHashtagClick = (element: HTMLAnchorElement) =>
|
||||
element.textContent?.[0] === '#' ||
|
||||
element.previousSibling?.textContent?.endsWith('#');
|
||||
|
||||
export const useLinks = () => {
|
||||
export const useLinks = (skipHashtags?: boolean) => {
|
||||
const history = useHistory();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
@@ -61,12 +62,12 @@ export const useLinks = () => {
|
||||
if (isMentionClick(target)) {
|
||||
e.preventDefault();
|
||||
void handleMentionClick(target);
|
||||
} else if (isHashtagClick(target)) {
|
||||
} else if (isHashtagClick(target) && !skipHashtags) {
|
||||
e.preventDefault();
|
||||
handleHashtagClick(target);
|
||||
}
|
||||
},
|
||||
[handleMentionClick, handleHashtagClick],
|
||||
[skipHashtags, handleMentionClick, handleHashtagClick],
|
||||
);
|
||||
|
||||
return handleClick;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// @ts-check
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {[code: string, name: string, localName: string]} InitialStateLanguage
|
||||
*/
|
||||
@@ -64,6 +63,7 @@
|
||||
* @property {boolean=} critical_updates_pending
|
||||
* @property {InitialStateMeta} meta
|
||||
* @property {Role?} role
|
||||
* @property {string[]} features
|
||||
*/
|
||||
|
||||
const element = document.getElementById('initial-state');
|
||||
@@ -140,4 +140,12 @@ export function getAccessToken() {
|
||||
return getMeta('access_token');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} feature
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function isFeatureEnabled(feature) {
|
||||
return initialState?.features?.includes(feature) || false;
|
||||
}
|
||||
|
||||
export default initialState;
|
||||
|
||||
@@ -219,6 +219,9 @@
|
||||
"confirmations.delete_list.confirm": "Elimina",
|
||||
"confirmations.delete_list.message": "Segur que vols suprimir permanentment aquesta llista?",
|
||||
"confirmations.delete_list.title": "Eliminar la llista?",
|
||||
"confirmations.discard_draft.confirm": "Descarta i continua",
|
||||
"confirmations.discard_draft.edit.cancel": "Continua l'edició",
|
||||
"confirmations.discard_draft.post.cancel": "Reprendre l'esborrany",
|
||||
"confirmations.discard_edit_media.confirm": "Descarta",
|
||||
"confirmations.discard_edit_media.message": "Tens canvis no desats en la descripció del contingut o en la previsualització, els vols descartar?",
|
||||
"confirmations.follow_to_list.confirm": "Seguir i afegir a una llista",
|
||||
@@ -792,6 +795,7 @@
|
||||
"report_notification.categories.violation": "Violació de norma",
|
||||
"report_notification.categories.violation_sentence": "violació de normes",
|
||||
"report_notification.open": "Obre l'informe",
|
||||
"search.clear": "Esborra la cerca",
|
||||
"search.no_recent_searches": "No hi ha cerques recents",
|
||||
"search.placeholder": "Cerca",
|
||||
"search.quick_action.account_search": "Perfils coincidint amb {x}",
|
||||
|
||||
@@ -386,7 +386,7 @@
|
||||
"follow_suggestions.similar_to_recently_followed_longer": "Minder om profiler, du har fulgt for nylig",
|
||||
"follow_suggestions.view_all": "Vis alle",
|
||||
"follow_suggestions.who_to_follow": "Hvem, som skal følges",
|
||||
"followed_tags": "Hashtag, som følges",
|
||||
"followed_tags": "Hashtags, som følges",
|
||||
"footer.about": "Om",
|
||||
"footer.directory": "Profiloversigt",
|
||||
"footer.get_app": "Hent appen",
|
||||
@@ -560,7 +560,7 @@
|
||||
"navigation_bar.favourites": "Favoritter",
|
||||
"navigation_bar.filters": "Skjulte ord",
|
||||
"navigation_bar.follow_requests": "Følgeanmodninger",
|
||||
"navigation_bar.followed_tags": "Hashtag, som følges",
|
||||
"navigation_bar.followed_tags": "Hashtags, som følges",
|
||||
"navigation_bar.follows_and_followers": "Følges og følgere",
|
||||
"navigation_bar.import_export": "Import og eksport",
|
||||
"navigation_bar.lists": "Lister",
|
||||
@@ -572,7 +572,7 @@
|
||||
"navigation_bar.mutes": "Skjulte brugere",
|
||||
"navigation_bar.opened_in_classic_interface": "Indlæg, konti og visse andre sider åbnes som standard i den klassiske webgrænseflade.",
|
||||
"navigation_bar.preferences": "Præferencer",
|
||||
"navigation_bar.privacy_and_reach": "Fortrolighed og udbredelse",
|
||||
"navigation_bar.privacy_and_reach": "Fortrolighed og rækkevidde",
|
||||
"navigation_bar.search": "Søg",
|
||||
"navigation_bar.search_trends": "Søg/Trender",
|
||||
"navigation_panel.collapse_followed_tags": "Sammenfold menuen Fulgte hashtags",
|
||||
|
||||
@@ -569,6 +569,7 @@
|
||||
"notification.admin.sign_up.name_and_others": "{name} eta {count, plural, one {erabiltzaile # gehiago} other {# erabiltzaile gehiago}} erregistratu dira",
|
||||
"notification.favourite": "{name}(e)k zure bidalketa gogoko du",
|
||||
"notification.favourite.name_and_others_with_link": "{name} eta <a>{count, plural, one {erabiltzaile # gehiagok} other {# erabiltzaile gehiagok}}</a> zure bidalketa gogoko dute",
|
||||
"notification.favourite_pm": "{name}-ek zure aipamen pribatua gogokoetan jarri du",
|
||||
"notification.follow": "{name}(e)k jarraitzen dizu",
|
||||
"notification.follow_request": "{name}(e)k zu jarraitzeko eskaera egin du",
|
||||
"notification.follow_request.name_and_others": "{name} eta {count, plural, one {erabiltzaile # gehiagok} other {# erabiltzaile gehiagok}} zu jarraitzeko eskaera egin dute",
|
||||
@@ -902,5 +903,7 @@
|
||||
"video.hide": "Ezkutatu bideoa",
|
||||
"video.pause": "Pausatu",
|
||||
"video.play": "Jo",
|
||||
"video.unmute": "Soinua ezarri",
|
||||
"video.volume_down": "Bolumena jaitsi",
|
||||
"video.volume_up": "Bolumena Igo"
|
||||
}
|
||||
|
||||
@@ -356,6 +356,7 @@
|
||||
"hashtag.counter_by_accounts": "{count, plural, one {{counter} partisipante} other {{counter} partisipantes}}",
|
||||
"hashtag.counter_by_uses": "{count, plural, one {{counter} publikasyon} other {{counter} publikasyones}}",
|
||||
"hashtag.counter_by_uses_today": "{count, plural, one {{counter} publikasyon} other {{counter} publikasyones}} oy",
|
||||
"hashtag.feature": "Avalia en profil",
|
||||
"hashtag.follow": "Sige etiketa",
|
||||
"hashtag.mute": "Silensia #{hashtag}",
|
||||
"hashtag.unfeature": "No avalia en profil",
|
||||
@@ -390,6 +391,7 @@
|
||||
"interaction_modal.title.reblog": "Repartaja publikasyon de {name}",
|
||||
"interaction_modal.title.reply": "Arisponde a publikasyon de {name}",
|
||||
"interaction_modal.title.vote": "Vota en la anketa de {name}",
|
||||
"interaction_modal.username_prompt": "Por enshemplo {example}",
|
||||
"intervals.full.days": "{number, plural, one {# diya} other {# diyas}}",
|
||||
"intervals.full.hours": "{number, plural, one {# ora} other {# oras}}",
|
||||
"intervals.full.minutes": "{number, plural, one {# minuto} other {# minutos}}",
|
||||
@@ -442,6 +444,7 @@
|
||||
"lists.delete": "Efasa lista",
|
||||
"lists.done": "Fecho",
|
||||
"lists.edit": "Edita lista",
|
||||
"lists.list_name": "Nombre de lista",
|
||||
"lists.new_list_name": "Nombre de mueva lista",
|
||||
"lists.replies_policy.followed": "Kualseker utilizador segido",
|
||||
"lists.replies_policy.list": "Miembros de la lista",
|
||||
@@ -738,6 +741,7 @@
|
||||
"status.reblogs.empty": "Ainda nadie tiene repartajado esta publikasyon. Kuando algien lo aga, se amostrara aki.",
|
||||
"status.redraft": "Efasa i eskrive de muevo",
|
||||
"status.remove_bookmark": "Kita markador",
|
||||
"status.remove_favourite": "Kita de los favoritos",
|
||||
"status.replied_in_thread": "Arispondo en filo",
|
||||
"status.replied_to": "Arispondio a {name}",
|
||||
"status.reply": "Arisponde",
|
||||
@@ -758,6 +762,7 @@
|
||||
"subscribed_languages.save": "Guadra trokamientos",
|
||||
"subscribed_languages.target": "Troka linguas abonadas para {target}",
|
||||
"tabs_bar.home": "Linya prinsipala",
|
||||
"tabs_bar.menu": "Menu",
|
||||
"tabs_bar.notifications": "Avizos",
|
||||
"tabs_bar.publish": "Mueva publikasyon",
|
||||
"tabs_bar.search": "Bushkeda",
|
||||
|
||||
@@ -126,6 +126,9 @@ export function createAccountFromServerJSON(serverJSON: ApiAccountJSON) {
|
||||
? accountJSON.username
|
||||
: accountJSON.display_name;
|
||||
|
||||
const accountNote =
|
||||
accountJSON.note && accountJSON.note !== '<p></p>' ? accountJSON.note : '';
|
||||
|
||||
return AccountFactory({
|
||||
...accountJSON,
|
||||
moved: moved?.id,
|
||||
@@ -142,8 +145,8 @@ export function createAccountFromServerJSON(serverJSON: ApiAccountJSON) {
|
||||
escapeTextContentForBrowser(displayName),
|
||||
emojiMap,
|
||||
),
|
||||
note_emojified: emojify(accountJSON.note, emojiMap),
|
||||
note_plain: unescapeHTML(accountJSON.note),
|
||||
note_emojified: emojify(accountNote, emojiMap),
|
||||
note_plain: unescapeHTML(accountNote),
|
||||
url:
|
||||
accountJSON.url.startsWith('http://') ||
|
||||
accountJSON.url.startsWith('https://')
|
||||
|
||||
Reference in New Issue
Block a user