this repo has no description
0
fork

Configure Feed

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

Better resolving of links

+79 -23
+51 -12
src/pages/http-route.jsx
··· 1 - import { useLayoutEffect } from 'preact/hooks'; 1 + import { useLayoutEffect, useState } from 'preact/hooks'; 2 2 import { useLocation } from 'react-router-dom'; 3 3 4 4 import Link from '../components/link'; 5 - import getInstanceStatusURL from '../utils/get-instance-status-url'; 5 + import Loader from '../components/loader'; 6 + import { api } from '../utils/api'; 7 + import getInstanceStatusURL, { 8 + getInstanceStatusObject, 9 + } from '../utils/get-instance-status-url'; 6 10 7 11 export default function HttpRoute() { 8 12 const location = useLocation(); 9 13 const url = location.pathname.replace(/^\//, ''); 10 - const statusURL = getInstanceStatusURL(url); 14 + const statusObject = getInstanceStatusObject(url); 15 + // const statusURL = getInstanceStatusURL(url); 16 + const statusURL = statusObject?.instance 17 + ? `/${statusObject.instance}/s/${statusObject.id}` 18 + : null; 19 + const [uiState, setUIState] = useState('loading'); 11 20 12 21 useLayoutEffect(() => { 13 - if (statusURL) { 14 - setTimeout(() => { 15 - window.location.hash = statusURL + '?view=full'; 16 - }, 300); 17 - } 22 + setUIState('loading'); 23 + (async () => { 24 + const { instance, id } = statusObject; 25 + const { masto } = api({ instance }); 26 + 27 + // Check if status returns 200 28 + try { 29 + const status = await masto.v1.statuses.$select(id).fetch(); 30 + if (status) { 31 + window.location.hash = statusURL + '?view=full'; 32 + return; 33 + } 34 + } catch (e) {} 35 + 36 + // Fallback to search 37 + { 38 + const { masto: currentMasto, instance: currentInstance } = api(); 39 + const result = await currentMasto.v2.search.fetch({ 40 + q: url, 41 + type: 'statuses', 42 + limit: 1, 43 + resolve: true, 44 + }); 45 + if (result.statuses.length) { 46 + const status = result.statuses[0]; 47 + window.location.hash = `/${currentInstance}/s/${status.id}?view=full`; 48 + } else { 49 + // Fallback to original URL, which will probably show error 50 + window.location.hash = statusURL + '?view=full'; 51 + } 52 + } 53 + })(); 18 54 }, [statusURL]); 19 55 20 56 return ( 21 57 <div class="ui-state" tabIndex="-1"> 22 - {statusURL ? ( 58 + {uiState === 'loading' ? ( 23 59 <> 24 - <h2>Redirecting…</h2> 60 + <Loader abrupt /> 61 + <h2>Resolving…</h2> 25 62 <p> 26 - <a href={`#${statusURL}?view=full`}>{statusURL}</a> 63 + <a href={url} target="_blank" rel="noopener noreferrer"> 64 + {url} 65 + </a> 27 66 </p> 28 67 </> 29 68 ) : ( 30 69 <> 31 - <h2>Unable to process URL</h2> 70 + <h2>Unable to resolve URL</h2> 32 71 <p> 33 72 <a href={url} target="_blank" rel="noopener noreferrer"> 34 73 {url}
+28 -11
src/utils/get-instance-status-url.js
··· 1 - export const statusRegex = /\/@([^@\/]+)@?([^\/]+)?\/([^\/]+)\/?$/i; 2 - export const statusNoteRegex = /\/notes\/([^\/]+)\/?$/i; 3 - function getInstanceStatusURL(url) { 1 + // export const statusRegex = /\/@([^@\/]+)@?([^\/]+)?\/([^\/]+)\/?$/i; 2 + // export const statusNoteRegex = /\/notes\/([^\/]+)\/?$/i; 3 + 4 + const statusPostRegexes = [ 5 + /^\/@[^@\/]+\/(?:statuses|posts)\/([^\/]+)/i, // GoToSocial, Takahe 6 + /\/notes\/([^\/]+)/i, // Misskey, Firefish 7 + /^\/(?:notice|objects)\/([a-z0-9-]+)/i, // Pleroma 8 + /\/@[^@\/]+@?[^\/]+?\/([^\/]+)/i, // Mastodon 9 + ]; 10 + 11 + export function getInstanceStatusObject(url) { 4 12 // Regex /:username/:id, where username = @username or @username@domain, id = anything 5 13 const { hostname, pathname } = new URL(url); 6 - const [, username, domain, id] = pathname.match(statusRegex) || []; 7 - 8 - if (id) { 9 - return `/${hostname}/s/${id}`; 14 + // const [, username, domain, id] = pathname.match(statusRegex) || []; 15 + for (const regex of statusPostRegexes) { 16 + const [, id] = pathname.match(regex) || []; 17 + console.log(pathname, regex, id); 18 + if (id) { 19 + return { 20 + instance: hostname, 21 + id, 22 + }; 23 + } 10 24 } 25 + return null; 26 + } 11 27 12 - const [, noteId] = pathname.match(statusNoteRegex) || []; 13 - 14 - if (noteId) { 15 - return `/${hostname}/s/${noteId}`; 28 + function getInstanceStatusURL(url) { 29 + const { instance, id } = getInstanceStatusObject(url); 30 + if (instance && id) { 31 + return `/${instance}/s/${id}`; 16 32 } 33 + return null; 17 34 } 18 35 19 36 export default getInstanceStatusURL;