commit
0a5d7267d5
716
package-lock.json
generated
716
package-lock.json
generated
File diff suppressed because it is too large
Load diff
12
package.json
12
package.json
|
@ -24,11 +24,11 @@
|
||||||
"masto": "~5.11.3",
|
"masto": "~5.11.3",
|
||||||
"mem": "~9.0.2",
|
"mem": "~9.0.2",
|
||||||
"p-retry": "~5.1.2",
|
"p-retry": "~5.1.2",
|
||||||
"p-throttle": "~5.0.0",
|
"p-throttle": "~5.1.0",
|
||||||
"preact": "~10.13.2",
|
"preact": "~10.15.0",
|
||||||
"react-hotkeys-hook": "~4.4.0",
|
"react-hotkeys-hook": "~4.4.0",
|
||||||
"react-intersection-observer": "~9.4.3",
|
"react-intersection-observer": "~9.4.3",
|
||||||
"react-quick-pinch-zoom": "~4.6.0",
|
"react-quick-pinch-zoom": "~4.9.0",
|
||||||
"react-router-dom": "6.6.2",
|
"react-router-dom": "6.6.2",
|
||||||
"string-length": "~5.0.1",
|
"string-length": "~5.0.1",
|
||||||
"swiped-events": "~1.1.7",
|
"swiped-events": "~1.1.7",
|
||||||
|
@ -44,12 +44,12 @@
|
||||||
"@trivago/prettier-plugin-sort-imports": "~4.1.1",
|
"@trivago/prettier-plugin-sort-imports": "~4.1.1",
|
||||||
"postcss": "~8.4.23",
|
"postcss": "~8.4.23",
|
||||||
"postcss-dark-theme-class": "~0.7.3",
|
"postcss-dark-theme-class": "~0.7.3",
|
||||||
"postcss-preset-env": "~8.3.2",
|
"postcss-preset-env": "~8.4.1",
|
||||||
"twitter-text": "~3.1.0",
|
"twitter-text": "~3.1.0",
|
||||||
"vite": "~4.3.5",
|
"vite": "~4.3.8",
|
||||||
"vite-plugin-generate-file": "~0.0.4",
|
"vite-plugin-generate-file": "~0.0.4",
|
||||||
"vite-plugin-html-config": "~1.0.11",
|
"vite-plugin-html-config": "~1.0.11",
|
||||||
"vite-plugin-pwa": "~0.14.7",
|
"vite-plugin-pwa": "~0.15.0",
|
||||||
"vite-plugin-remove-console": "~2.1.1",
|
"vite-plugin-remove-console": "~2.1.1",
|
||||||
"workbox-cacheable-response": "~6.5.4",
|
"workbox-cacheable-response": "~6.5.4",
|
||||||
"workbox-expiration": "~6.5.4",
|
"workbox-expiration": "~6.5.4",
|
||||||
|
|
|
@ -59,8 +59,9 @@ registerRoute(iconsRoute);
|
||||||
// - /api/v1/custom_emojis
|
// - /api/v1/custom_emojis
|
||||||
// - /api/v1/preferences
|
// - /api/v1/preferences
|
||||||
// - /api/v1/lists/:id
|
// - /api/v1/lists/:id
|
||||||
|
// - /api/v1/announcements
|
||||||
const apiExtendedRoute = new RegExpRoute(
|
const apiExtendedRoute = new RegExpRoute(
|
||||||
/^https?:\/\/[^\/]+\/api\/v\d+\/(instance|custom_emojis|preferences|lists\/\d+)$/,
|
/^https?:\/\/[^\/]+\/api\/v\d+\/(instance|custom_emojis|preferences|lists\/\d+|announcements)$/,
|
||||||
new StaleWhileRevalidate({
|
new StaleWhileRevalidate({
|
||||||
cacheName: 'api-extended',
|
cacheName: 'api-extended',
|
||||||
plugins: [
|
plugins: [
|
||||||
|
|
|
@ -262,10 +262,10 @@ a[href^='http'][rel*='nofollow']:visited:not(:has(div)) {
|
||||||
inset 0 3px var(--comment-line-color);
|
inset 0 3px var(--comment-line-color);
|
||||||
}
|
}
|
||||||
.timeline.contextual .replies[data-comments-level='4'] {
|
.timeline.contextual .replies[data-comments-level='4'] {
|
||||||
overflow: auto;
|
overflow-x: auto;
|
||||||
}
|
}
|
||||||
.timeline.contextual .replies[data-comments-level='4']:has(.replies) {
|
.timeline.contextual .replies[data-comments-level='4']:has(.replies) {
|
||||||
overflow: auto;
|
overflow-x: auto;
|
||||||
mask-image: linear-gradient(to left, transparent, black 32px);
|
mask-image: linear-gradient(to left, transparent, black 32px);
|
||||||
}
|
}
|
||||||
.timeline.contextual
|
.timeline.contextual
|
||||||
|
|
|
@ -91,7 +91,9 @@ function App() {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const instanceURL = store.local.get('instanceURL');
|
const instanceURL = store.local.get('instanceURL');
|
||||||
const code = (window.location.search.match(/code=([^&]+)/) || [])[1];
|
const code = decodeURIComponent(
|
||||||
|
(window.location.search.match(/code=([^&]+)/) || [, ''])[1],
|
||||||
|
);
|
||||||
|
|
||||||
if (code) {
|
if (code) {
|
||||||
console.log({ code });
|
console.log({ code });
|
||||||
|
|
3
src/assets/phanpy-bg.svg
Normal file
3
src/assets/phanpy-bg.svg
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 90 85">
|
||||||
|
<path fill="#fff" fill-opacity="0.4" fill-rule="evenodd" d="M88 64c6.4-29.6-2.4-55.2-31.7-62.7C31.9-4.9 8.1 11.6.8 42c-3.3 13.8 3.3 30.3 24.6 35.6l19.3 4.8c14.5 4 24.3 2.3 30.7-1.1a25 25 0 0 0 12.7-17.4Zm-8-1.8c5.4-24.7-1.1-46.7-25.7-53C34 4 14.8 18.6 8.8 44c-2.5 10.2 2.9 22 18.6 25.8l19.4 4.8c23.4 6.4 31.4-3.4 33.3-12.3ZM35.8 28.4c-3-1.4-14.5 6.4-15.3 17.8-.4 4.8 9 6.5 10.1-.3.7-4.8 2.6-9 4-12s2.3-5 1.2-5.5Zm19.8 15c-.5-5.9-1-10.6 1.7-11 4-.7 10.4 15.3 8.2 25.4-.6 3-9.6 1.6-9.4-4 .2-3.5-.2-7.1-.5-10.4Z" clip-rule="evenodd"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 614 B |
|
@ -493,7 +493,7 @@ function RelatedActions({ info, instance, authenticated }) {
|
||||||
>
|
>
|
||||||
<div class="shazam-container-inner">
|
<div class="shazam-container-inner">
|
||||||
<p>
|
<p>
|
||||||
Also followed by{' '}
|
Followed by{' '}
|
||||||
<span class="ib">
|
<span class="ib">
|
||||||
{familiarFollowers.map((follower) => (
|
{familiarFollowers.map((follower) => (
|
||||||
<a
|
<a
|
||||||
|
|
|
@ -388,6 +388,7 @@
|
||||||
background-color: var(--bg-faded-color);
|
background-color: var(--bg-faded-color);
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
margin: 8px 0 0;
|
margin: 8px 0 0;
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
#compose-container .poll-choices {
|
#compose-container .poll-choices {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import './compose.css';
|
import './compose.css';
|
||||||
|
|
||||||
import { match } from '@formatjs/intl-localematcher';
|
|
||||||
import '@github/text-expander-element';
|
import '@github/text-expander-element';
|
||||||
import equal from 'fast-deep-equal';
|
import equal from 'fast-deep-equal';
|
||||||
import { forwardRef } from 'preact/compat';
|
import { forwardRef } from 'preact/compat';
|
||||||
|
@ -16,6 +15,7 @@ import urlRegex from '../data/url-regex';
|
||||||
import { api } from '../utils/api';
|
import { api } from '../utils/api';
|
||||||
import db from '../utils/db';
|
import db from '../utils/db';
|
||||||
import emojifyText from '../utils/emojify-text';
|
import emojifyText from '../utils/emojify-text';
|
||||||
|
import localeMatch from '../utils/locale-match';
|
||||||
import openCompose from '../utils/open-compose';
|
import openCompose from '../utils/open-compose';
|
||||||
import states, { saveStatus } from '../utils/states';
|
import states, { saveStatus } from '../utils/states';
|
||||||
import store from '../utils/store';
|
import store from '../utils/store';
|
||||||
|
@ -85,7 +85,7 @@ const observer = new IntersectionObserver((entries) => {
|
||||||
});
|
});
|
||||||
observer.observe(menu);
|
observer.observe(menu);
|
||||||
|
|
||||||
const DEFAULT_LANG = match(
|
const DEFAULT_LANG = localeMatch(
|
||||||
[new Intl.DateTimeFormat().resolvedOptions().locale, ...navigator.languages],
|
[new Intl.DateTimeFormat().resolvedOptions().locale, ...navigator.languages],
|
||||||
supportedLanguages.map((l) => l[0]),
|
supportedLanguages.map((l) => l[0]),
|
||||||
'en',
|
'en',
|
||||||
|
|
43
src/components/nav-menu.css
Normal file
43
src/components/nav-menu.css
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
@media (min-width: 23em) {
|
||||||
|
.nav-menu {
|
||||||
|
display: flex;
|
||||||
|
width: auto;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.nav-menu section {
|
||||||
|
padding: 8px 0;
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
@keyframes phanpying {
|
||||||
|
0% {
|
||||||
|
background-position: 0 0, 0 0, 3em 85%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 0 0, 0 0, 2em 90%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.nav-menu section:last-child {
|
||||||
|
background-color: var(--bg-faded-color);
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to right,
|
||||||
|
var(--divider-color) 1px,
|
||||||
|
transparent 1px
|
||||||
|
),
|
||||||
|
linear-gradient(to bottom left, var(--bg-blur-color), transparent),
|
||||||
|
url(../assets/phanpy-bg.svg);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
/* background-size: auto, auto, 200%; */
|
||||||
|
background-position: 0 0, 0 0, 2em 90%;
|
||||||
|
background-blend-mode: normal, normal, overlay;
|
||||||
|
box-shadow: inset 0 0 1px var(--bg-color);
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
animation: phanpying 0.2s ease-in-out both;
|
||||||
|
}
|
||||||
|
.nav-menu section:last-child > .szh-menu__divider:first-child {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.nav-menu .szh-menu__item span {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,7 @@
|
||||||
import {
|
import './nav-menu.css';
|
||||||
ControlledMenu,
|
|
||||||
MenuDivider,
|
import { ControlledMenu, MenuDivider, MenuItem } from '@szhsin/react-menu';
|
||||||
MenuItem,
|
import { useRef, useState } from 'preact/hooks';
|
||||||
useClick,
|
|
||||||
useMenuState,
|
|
||||||
} from '@szhsin/react-menu';
|
|
||||||
import { useRef } from 'preact/hooks';
|
|
||||||
import { useLongPress } from 'use-long-press';
|
import { useLongPress } from 'use-long-press';
|
||||||
import { useSnapshot } from 'valtio';
|
import { useSnapshot } from 'valtio';
|
||||||
|
|
||||||
|
@ -47,8 +43,7 @@ function NavMenu(props) {
|
||||||
);
|
);
|
||||||
|
|
||||||
const buttonRef = useRef();
|
const buttonRef = useRef();
|
||||||
const [menuState, toggleMenu] = useMenuState();
|
const [menuState, setMenuState] = useState(undefined);
|
||||||
const anchorProps = useClick(menuState.state, toggleMenu);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -59,7 +54,9 @@ function NavMenu(props) {
|
||||||
moreThanOneAccount ? 'with-avatar' : ''
|
moreThanOneAccount ? 'with-avatar' : ''
|
||||||
} ${open ? 'active' : ''}`}
|
} ${open ? 'active' : ''}`}
|
||||||
style={{ position: 'relative' }}
|
style={{ position: 'relative' }}
|
||||||
{...anchorProps}
|
onClick={() => {
|
||||||
|
setMenuState((state) => (!state ? 'open' : undefined));
|
||||||
|
}}
|
||||||
onContextMenu={(e) => {
|
onContextMenu={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
states.showAccounts = true;
|
states.showAccounts = true;
|
||||||
|
@ -78,17 +75,18 @@ function NavMenu(props) {
|
||||||
<Icon icon="menu" size={moreThanOneAccount ? 's' : 'l'} />
|
<Icon icon="menu" size={moreThanOneAccount ? 's' : 'l'} />
|
||||||
</button>
|
</button>
|
||||||
<ControlledMenu
|
<ControlledMenu
|
||||||
{...menuState}
|
menuClassName="nav-menu"
|
||||||
|
state={menuState}
|
||||||
anchorRef={buttonRef}
|
anchorRef={buttonRef}
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
toggleMenu(false);
|
setMenuState(undefined);
|
||||||
}}
|
}}
|
||||||
containerProps={{
|
containerProps={{
|
||||||
style: {
|
style: {
|
||||||
zIndex: 10,
|
zIndex: 10,
|
||||||
},
|
},
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
toggleMenu(false);
|
setMenuState(undefined);
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
portal={{
|
portal={{
|
||||||
|
@ -102,6 +100,7 @@ function NavMenu(props) {
|
||||||
boundingBoxPadding="8 8 8 8"
|
boundingBoxPadding="8 8 8 8"
|
||||||
unmountOnClose
|
unmountOnClose
|
||||||
>
|
>
|
||||||
|
<section>
|
||||||
{!!snapStates.appVersion?.commitHash &&
|
{!!snapStates.appVersion?.commitHash &&
|
||||||
__COMMIT_HASH__ !== snapStates.appVersion.commitHash && (
|
__COMMIT_HASH__ !== snapStates.appVersion.commitHash && (
|
||||||
<>
|
<>
|
||||||
|
@ -173,6 +172,8 @@ function NavMenu(props) {
|
||||||
<MenuLink to={`/${instance}/trending`}>
|
<MenuLink to={`/${instance}/trending`}>
|
||||||
<Icon icon="chart" size="l" /> <span>Trending</span>
|
<Icon icon="chart" size="l" /> <span>Trending</span>
|
||||||
</MenuLink>
|
</MenuLink>
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
{authenticated && (
|
{authenticated && (
|
||||||
<>
|
<>
|
||||||
<MenuDivider />
|
<MenuDivider />
|
||||||
|
@ -205,6 +206,7 @@ function NavMenu(props) {
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
</section>
|
||||||
</ControlledMenu>
|
</ControlledMenu>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -518,7 +518,7 @@
|
||||||
.status .content > div > :is(ul, ol) {
|
.status .content > div > :is(ul, ol) {
|
||||||
margin-block: min(0.75em, 12px);
|
margin-block: min(0.75em, 12px);
|
||||||
margin-inline: 0;
|
margin-inline: 0;
|
||||||
padding-inline-start: 1em;
|
padding-inline-start: 1.5em;
|
||||||
}
|
}
|
||||||
.status .content .invisible {
|
.status .content .invisible {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import './status.css';
|
import './status.css';
|
||||||
|
|
||||||
import { match } from '@formatjs/intl-localematcher';
|
|
||||||
import '@justinribeiro/lite-youtube';
|
import '@justinribeiro/lite-youtube';
|
||||||
import {
|
import {
|
||||||
ControlledMenu,
|
ControlledMenu,
|
||||||
|
@ -33,6 +32,7 @@ import getHTMLText from '../utils/getHTMLText';
|
||||||
import handleContentLinks from '../utils/handle-content-links';
|
import handleContentLinks from '../utils/handle-content-links';
|
||||||
import htmlContentLength from '../utils/html-content-length';
|
import htmlContentLength from '../utils/html-content-length';
|
||||||
import isMastodonLinkMaybe from '../utils/isMastodonLinkMaybe';
|
import isMastodonLinkMaybe from '../utils/isMastodonLinkMaybe';
|
||||||
|
import localeMatch from '../utils/locale-match';
|
||||||
import niceDateTime from '../utils/nice-date-time';
|
import niceDateTime from '../utils/nice-date-time';
|
||||||
import shortenNumber from '../utils/shorten-number';
|
import shortenNumber from '../utils/shorten-number';
|
||||||
import showToast from '../utils/show-toast';
|
import showToast from '../utils/show-toast';
|
||||||
|
@ -105,10 +105,11 @@ function Status({
|
||||||
const { instance: currentInstance } = api();
|
const { instance: currentInstance } = api();
|
||||||
const sameInstance = instance === currentInstance;
|
const sameInstance = instance === currentInstance;
|
||||||
|
|
||||||
const sKey = statusKey(statusID, instance);
|
let sKey = statusKey(statusID, instance);
|
||||||
const snapStates = useSnapshot(states);
|
const snapStates = useSnapshot(states);
|
||||||
if (!status) {
|
if (!status) {
|
||||||
status = snapStates.statuses[sKey] || snapStates.statuses[statusID];
|
status = snapStates.statuses[sKey] || snapStates.statuses[statusID];
|
||||||
|
sKey = statusKey(status?.id, instance);
|
||||||
}
|
}
|
||||||
if (!status) {
|
if (!status) {
|
||||||
return null;
|
return null;
|
||||||
|
@ -408,9 +409,9 @@ function Status({
|
||||||
const differentLanguage =
|
const differentLanguage =
|
||||||
language &&
|
language &&
|
||||||
language !== targetLanguage &&
|
language !== targetLanguage &&
|
||||||
!match([language], [targetLanguage]) &&
|
!localeMatch([language], [targetLanguage]) &&
|
||||||
!contentTranslationHideLanguages.find(
|
!contentTranslationHideLanguages.find(
|
||||||
(l) => language === l || match([language], [l]),
|
(l) => language === l || localeMatch([language], [l]),
|
||||||
);
|
);
|
||||||
|
|
||||||
const menuInstanceRef = useRef();
|
const menuInstanceRef = useRef();
|
||||||
|
@ -977,6 +978,7 @@ function Status({
|
||||||
(result) => {
|
(result) => {
|
||||||
if (!result) return;
|
if (!result) return;
|
||||||
a.removeAttribute('target');
|
a.removeAttribute('target');
|
||||||
|
if (!sKey) return;
|
||||||
if (!Array.isArray(states.statusQuotes[sKey])) {
|
if (!Array.isArray(states.statusQuotes[sKey])) {
|
||||||
states.statusQuotes[sKey] = [];
|
states.statusQuotes[sKey] = [];
|
||||||
}
|
}
|
||||||
|
@ -1102,7 +1104,7 @@ function Status({
|
||||||
<>
|
<>
|
||||||
<Icon
|
<Icon
|
||||||
icon={visibilityIconsMap[visibility]}
|
icon={visibilityIconsMap[visibility]}
|
||||||
alt={visibility}
|
alt={visibilityText[visibility]}
|
||||||
/>{' '}
|
/>{' '}
|
||||||
<a href={url} target="_blank">
|
<a href={url} target="_blank">
|
||||||
<time
|
<time
|
||||||
|
@ -1954,6 +1956,7 @@ function FilteredStatus({ status, filterInfo, instance, containerProps = {} }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const QuoteStatuses = memo(({ id, instance, level = 0 }) => {
|
const QuoteStatuses = memo(({ id, instance, level = 0 }) => {
|
||||||
|
if (!id || !instance) return;
|
||||||
const snapStates = useSnapshot(states);
|
const snapStates = useSnapshot(states);
|
||||||
const sKey = statusKey(id, instance);
|
const sKey = statusKey(id, instance);
|
||||||
const quotes = snapStates.statusQuotes[sKey];
|
const quotes = snapStates.statusQuotes[sKey];
|
||||||
|
|
|
@ -103,14 +103,11 @@ function Notifications() {
|
||||||
setUIState('loading');
|
setUIState('loading');
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
const fetchNotificationsPromise = fetchNotifications(firstLoad);
|
||||||
const fetchFollowRequestsPromise = fetchFollowRequests();
|
const fetchFollowRequestsPromise = fetchFollowRequests();
|
||||||
const fetchAnnouncementsPromise = fetchAnnouncements();
|
const fetchAnnouncementsPromise = fetchAnnouncements();
|
||||||
const { done } = await fetchNotifications(firstLoad);
|
|
||||||
setShowMore(!done);
|
|
||||||
|
|
||||||
if (firstLoad) {
|
if (firstLoad) {
|
||||||
const requests = await fetchFollowRequestsPromise;
|
|
||||||
setFollowRequests(requests);
|
|
||||||
const announcements = await fetchAnnouncementsPromise;
|
const announcements = await fetchAnnouncementsPromise;
|
||||||
announcements.sort((a, b) => {
|
announcements.sort((a, b) => {
|
||||||
// Sort by updatedAt first, then createdAt
|
// Sort by updatedAt first, then createdAt
|
||||||
|
@ -119,8 +116,13 @@ function Notifications() {
|
||||||
return bDate - aDate;
|
return bDate - aDate;
|
||||||
});
|
});
|
||||||
setAnnouncements(announcements);
|
setAnnouncements(announcements);
|
||||||
|
const requests = await fetchFollowRequestsPromise;
|
||||||
|
setFollowRequests(requests);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { done } = await fetchNotificationsPromise;
|
||||||
|
setShowMore(!done);
|
||||||
|
|
||||||
setUIState('default');
|
setUIState('default');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setUIState('error');
|
setUIState('error');
|
||||||
|
|
|
@ -248,10 +248,17 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
||||||
|
|
||||||
totalDescendants.current = descendants?.length || 0;
|
totalDescendants.current = descendants?.length || 0;
|
||||||
|
|
||||||
|
const missingStatuses = new Set();
|
||||||
ancestors.forEach((status) => {
|
ancestors.forEach((status) => {
|
||||||
saveStatus(status, instance, {
|
saveStatus(status, instance, {
|
||||||
skipThreading: true,
|
skipThreading: true,
|
||||||
});
|
});
|
||||||
|
if (
|
||||||
|
status.inReplyToId &&
|
||||||
|
!ancestors.find((s) => s.id === status.inReplyToId)
|
||||||
|
) {
|
||||||
|
missingStatuses.add(status.inReplyToId);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const ancestorsIsThread = ancestors.every(
|
const ancestorsIsThread = ancestors.every(
|
||||||
(s) => s.account.id === heroStatus.account.id,
|
(s) => s.account.id === heroStatus.account.id,
|
||||||
|
@ -261,6 +268,15 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
||||||
saveStatus(status, instance, {
|
saveStatus(status, instance, {
|
||||||
skipThreading: true,
|
skipThreading: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (
|
||||||
|
status.inReplyToId &&
|
||||||
|
!descendants.find((s) => s.id === status.inReplyToId) &&
|
||||||
|
status.inReplyToId !== heroStatus.id
|
||||||
|
) {
|
||||||
|
missingStatuses.add(status.inReplyToId);
|
||||||
|
}
|
||||||
|
|
||||||
if (status.inReplyToAccountId === status.account.id) {
|
if (status.inReplyToAccountId === status.account.id) {
|
||||||
// If replying to self, it's part of the thread, level 1
|
// If replying to self, it's part of the thread, level 1
|
||||||
nestedDescendants.push(status);
|
nestedDescendants.push(status);
|
||||||
|
@ -290,6 +306,9 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log({ ancestors, descendants, nestedDescendants });
|
console.log({ ancestors, descendants, nestedDescendants });
|
||||||
|
if (missingStatuses.size) {
|
||||||
|
console.error('Missing statuses', [...missingStatuses]);
|
||||||
|
}
|
||||||
|
|
||||||
function expandReplies(_replies) {
|
function expandReplies(_replies) {
|
||||||
return _replies?.map((_r) => ({
|
return _replies?.map((_r) => ({
|
||||||
|
@ -591,14 +610,17 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
|
||||||
|
|
||||||
const initialPageState = useRef(showMedia ? 'media+status' : 'status');
|
const initialPageState = useRef(showMedia ? 'media+status' : 'status');
|
||||||
|
|
||||||
const handleMediaClick = useCallback((e, i, media, status) => {
|
const handleMediaClick = useCallback(
|
||||||
|
(e, i, media, status) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
setSearchParams({
|
setSearchParams({
|
||||||
media: i + 1,
|
media: i + 1,
|
||||||
mediaStatusID: status.id,
|
mediaStatusID: status.id,
|
||||||
});
|
});
|
||||||
}, []);
|
},
|
||||||
|
[id],
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { match } from '@formatjs/intl-localematcher';
|
|
||||||
|
|
||||||
import translationTargetLanguages from '../data/lingva-target-languages';
|
import translationTargetLanguages from '../data/lingva-target-languages';
|
||||||
|
|
||||||
|
import localeMatch from './locale-match';
|
||||||
import states from './states';
|
import states from './states';
|
||||||
|
|
||||||
function getTranslateTargetLanguage(fromSettings = false) {
|
function getTranslateTargetLanguage(fromSettings = false) {
|
||||||
|
@ -11,7 +10,7 @@ function getTranslateTargetLanguage(fromSettings = false) {
|
||||||
return contentTranslationTargetLanguage;
|
return contentTranslationTargetLanguage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return match(
|
return localeMatch(
|
||||||
[
|
[
|
||||||
new Intl.DateTimeFormat().resolvedOptions().locale,
|
new Intl.DateTimeFormat().resolvedOptions().locale,
|
||||||
...navigator.languages,
|
...navigator.languages,
|
||||||
|
|
12
src/utils/locale-match.jsx
Normal file
12
src/utils/locale-match.jsx
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { match } from '@formatjs/intl-localematcher';
|
||||||
|
|
||||||
|
function localeMatch(...args) {
|
||||||
|
// Wrap in try/catch because localeMatcher throws on invalid locales
|
||||||
|
try {
|
||||||
|
return match(...args);
|
||||||
|
} catch (e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default localeMatch;
|
|
@ -110,6 +110,7 @@ export function hideAllModals() {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function statusKey(id, instance) {
|
export function statusKey(id, instance) {
|
||||||
|
if (!id) return;
|
||||||
return instance ? `${instance}/${id}` : id;
|
return instance ? `${instance}/${id}` : id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue