this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Experimental feature: translate bio

+67 -15
+52 -2
src/components/account-info.jsx
··· 9 9 } from '@szhsin/react-menu'; 10 10 import { useEffect, useRef, useState } from 'preact/hooks'; 11 11 12 - import RelativeTime from '../components/relative-time'; 13 12 import { api } from '../utils/api'; 14 13 import emojifyText from '../utils/emojify-text'; 15 14 import enhanceContent from '../utils/enhance-content'; 15 + import getHTMLText from '../utils/getHTMLText'; 16 16 import handleContentLinks from '../utils/handle-content-links'; 17 17 import niceDateTime from '../utils/nice-date-time'; 18 18 import shortenNumber from '../utils/shorten-number'; ··· 24 24 import Avatar from './avatar'; 25 25 import Icon from './icon'; 26 26 import Link from './link'; 27 + import Modal from './modal'; 28 + import TranslationBlock from './translation-block'; 27 29 28 30 const MUTE_DURATIONS = [ 29 31 1000 * 60 * 5, // 5 minutes ··· 389 391 const [relationship, setRelationship] = useState(null); 390 392 const [familiarFollowers, setFamiliarFollowers] = useState([]); 391 393 392 - const { id, acct, url, username, locked, lastStatusAt } = info; 394 + const { id, acct, url, username, locked, lastStatusAt, note, fields } = info; 393 395 const accountID = useRef(id); 394 396 395 397 const { ··· 484 486 const loading = relationshipUIState === 'loading'; 485 487 const menuInstanceRef = useRef(null); 486 488 489 + const [showTranslatedBio, setShowTranslatedBio] = useState(false); 490 + 487 491 return ( 488 492 <> 489 493 {familiarFollowers?.length > 0 && ( ··· 571 575 <Icon icon="at" /> 572 576 <span>Mention @{username}</span> 573 577 </MenuItem> 578 + <MenuItem 579 + onClick={() => { 580 + setShowTranslatedBio(true); 581 + }} 582 + > 583 + <Icon icon="translate" /> 584 + <span>Translate bio</span> 585 + </MenuItem> 574 586 <MenuDivider /> 575 587 </> 576 588 )} ··· 816 828 )} 817 829 </span> 818 830 </p> 831 + {!!showTranslatedBio && ( 832 + <Modal 833 + class="light" 834 + onClick={(e) => { 835 + if (e.target === e.currentTarget) { 836 + setShowTranslatedBio(false); 837 + } 838 + }} 839 + > 840 + <TranslatedBioSheet note={note} fields={fields} /> 841 + </Modal> 842 + )} 819 843 </> 820 844 ); 821 845 } ··· 850 874 ); 851 875 } 852 876 877 + function TranslatedBioSheet({ note, fields }) { 878 + const fieldsText = 879 + fields 880 + ?.map(({ name, value }) => `${name}\n${getHTMLText(value)}`) 881 + .join('\n\n') || ''; 882 + 883 + const text = getHTMLText(note) + (fieldsText ? `\n\n${fieldsText}` : ''); 884 + 885 + return ( 886 + <div class="sheet"> 887 + <header> 888 + <h2>Translated Bio</h2> 889 + </header> 890 + <main> 891 + <p 892 + style={{ 893 + whiteSpace: 'pre-wrap', 894 + }} 895 + > 896 + {text} 897 + </p> 898 + <TranslationBlock forceTranslate text={text} /> 899 + </main> 900 + </div> 901 + ); 902 + } 853 903 export default AccountInfo;
+1 -12
src/components/status.jsx
··· 25 25 import { api } from '../utils/api'; 26 26 import enhanceContent from '../utils/enhance-content'; 27 27 import getTranslateTargetLanguage from '../utils/get-translate-target-language'; 28 + import getHTMLText from '../utils/getHTMLText'; 28 29 import handleContentLinks from '../utils/handle-content-links'; 29 30 import htmlContentLength from '../utils/html-content-length'; 30 31 import niceDateTime from '../utils/nice-date-time'; ··· 1694 1695 } 1695 1696 1696 1697 const unfurlMastodonLink = throttle(_unfurlMastodonLink); 1697 - 1698 - const div = document.createElement('div'); 1699 - export function getHTMLText(html) { 1700 - if (!html) return ''; 1701 - div.innerHTML = html 1702 - .replace(/<\/p>/g, '</p>\n\n') 1703 - .replace(/<\/li>/g, '</li>\n'); 1704 - div.querySelectorAll('br').forEach((br) => { 1705 - br.replaceWith('\n'); 1706 - }); 1707 - return div.innerText.replace(/[\r\n]{3,}/g, '\n\n').trim(); 1708 - } 1709 1698 1710 1699 const root = document.documentElement; 1711 1700 const defaultBoundingBoxPadding = 8;
+13
src/utils/getHTMLText.jsx
··· 1 + const div = document.createElement('div'); 2 + function getHTMLText(html) { 3 + if (!html) return ''; 4 + div.innerHTML = html 5 + .replace(/<\/p>/g, '</p>\n\n') 6 + .replace(/<\/li>/g, '</li>\n'); 7 + div.querySelectorAll('br').forEach((br) => { 8 + br.replaceWith('\n'); 9 + }); 10 + return div.innerText.replace(/[\r\n]{3,}/g, '\n\n').trim(); 11 + } 12 + 13 + export default getHTMLText;
+1 -1
src/utils/status-peek.jsx
··· 1 - import { getHTMLText } from '../components/status'; 1 + import getHTMLText from './getHTMLText'; 2 2 3 3 function statusPeek(status) { 4 4 const { spoilerText, content, poll, mediaAttachments } = status;