Skip to content

Commit

Permalink
can directly link to profile and will resolve the url to agora compat…
Browse files Browse the repository at this point in the history
…ible link
  • Loading branch information
ghobs91 committed Feb 29, 2024
1 parent 4dfb56f commit 154e7e9
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 31 deletions.
7 changes: 4 additions & 3 deletions src/pages/account-statuses.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function AccountStatuses() {
[instance],
);
const [searchEnabled, setSearchEnabled] = useState(false);
const canAutoSwitchToUsersInstance = () => {
const canAutoSwitchToUsersInstance = async () => {
return account?.acct && account?.acct.indexOf('bird.makeup') === -1 && account?.acct.indexOf('threads.net') === -1;
}
useEffect(() => {
Expand All @@ -86,8 +86,9 @@ function AccountStatuses() {
const { id } = acc;
location.hash = `/${accountInstance}/a/${id}`;
} catch (e) {
console.error(e);
alert('Unable to fetch account info');
return;
// console.error(e);
// alert('Unable to fetch account info');
}
})();
}
Expand Down
5 changes: 3 additions & 2 deletions src/pages/forYou.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,14 @@ function ForYou(props) {
return (
<>
<Timeline
key={id}
key={instance}
title={list.title}
id="list"
id="foryou"
emptyText="Nothing yet."
errorText="Unable to load posts."
instance={instance}
fetchItems={fetchList}
checkForUpdates={checkForUpdates}
useItemID
boostsCarousel={snapStates.settings.boostsCarousel}
allowFilters
Expand Down
68 changes: 55 additions & 13 deletions src/pages/http-route.jsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,76 @@
import { useLayoutEffect } from 'preact/hooks';
import { useLayoutEffect, useState } from 'preact/hooks';
import { useLocation } from 'react-router-dom';

import Link from '../components/link';
import getInstanceStatusURL from '../utils/get-instance-status-url';
import Loader from '../components/loader';
import { api } from '../utils/api';
import getInstanceStatusURL, {
getInstanceStatusObject,
} from '../utils/get-instance-status-url';

export default function HttpRoute() {
const location = useLocation();
const url = location.pathname.replace(/^\//, '');
const statusURL = getInstanceStatusURL(url);
const statusObject = getInstanceStatusObject(url);
// const statusURL = getInstanceStatusURL(url);
const statusURL = statusObject?.instance
? `/${statusObject.instance}/s/${statusObject.id}`
: null;
const [uiState, setUIState] = useState('loading');

useLayoutEffect(() => {
if (statusURL) {
setTimeout(() => {
window.location.hash = statusURL + '?view=full';
}, 300);
}
setUIState('loading');
(async () => {
// Check if status returns 200
try {
const { instance, id } = statusObject;
const { masto } = api({ instance });
const status = await masto.v1.statuses.$select(id).fetch();
if (status) {
window.location.hash = statusURL + '?view=full';
return;
}
} catch (e) {}

// Fallback to search
{
const { masto: currentMasto, instance: currentInstance } = api();
const result = await currentMasto.v2.search.fetch({
q: url,
limit: 1,
resolve: true,
});
if (result.statuses.length) {
const status = result.statuses[0];
window.location.hash = `/${currentInstance}/s/${status.id}?view=full`;
} else if (result.accounts.length) {
const account = result.accounts[0];
window.location.hash = `/${currentInstance}/a/${account.id}`;
} else if (statusURL) {
// Fallback to original URL, which will probably show error
window.location.hash = statusURL + '?view=full';
} else {
setUIState('error');
}
}
})();
}, [statusURL]);

return (
<div class="ui-state" tabIndex="-1">
{statusURL ? (
{uiState === 'loading' ? (
<>
<h2>Redirecting…</h2>
<Loader abrupt />
<h2>Searching…</h2>
<p>
<a href={`#${statusURL}?view=full`}>{statusURL}</a>
<a href={url} target="_blank" rel="noopener noreferrer">
{url}
</a>
</p>
</>
) : (
<>
<h2>Unable to process URL</h2>
<h2>Unable to resolve URL</h2>
<p>
<a href={url} target="_blank" rel="noopener noreferrer">
{url}
Expand All @@ -42,4 +84,4 @@ export default function HttpRoute() {
</p>
</div>
);
}
}
10 changes: 9 additions & 1 deletion src/pages/status.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
const autoLoadLocalInstanceVersion = () => {
setUIState('loading');
(async () => {
try {
try {autoLoadLocalInstanceVersion
const apiEndpoint = currentMasto ? currentMasto : myCurrentInstance
const results =
await apiEndpoint.v2.search.fetch({
Expand Down Expand Up @@ -307,6 +307,14 @@ function StatusThread({ id, closeLink = '/', instance: propInstance }) {
}

try {
async () => {
const statusURL = getInstanceStatusURL(heroStatus.url);
if (statusURL) {
location.hash = statusURL;
} else {
alert('Unable to switch');
}
}
const context = await contextFetch;
const { ancestors, descendants } = context;

Expand Down
41 changes: 29 additions & 12 deletions src/utils/get-instance-status-url.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
export const statusRegex = /\/@([^@\/]+)@?([^\/]+)?\/([^\/]+)\/?$/i;
export const statusNoteRegex = /\/notes\/([^\/]+)\/?$/i;
function getInstanceStatusURL(url) {
// export const statusRegex = /\/@([^@\/]+)@?([^\/]+)?\/([^\/]+)\/?$/i;
// export const statusNoteRegex = /\/notes\/([^\/]+)\/?$/i;

const statusPostRegexes = [
/^\/@[^@\/]+\/(?:statuses|posts)\/([^\/]+)/i, // GoToSocial, Takahe
/\/notes\/([^\/]+)/i, // Misskey, Firefish
/^\/(?:notice|objects)\/([a-z0-9-]+)/i, // Pleroma
/\/@[^@\/]+@?[^\/]+?\/([^\/]+)/i, // Mastodon
];

export function getInstanceStatusObject(url) {
// Regex /:username/:id, where username = @username or @username@domain, id = anything
const { hostname, pathname } = new URL(url);
const [, username, domain, id] = pathname.match(statusRegex) || [];

if (id) {
return `/${hostname}/s/${id}`;
// const [, username, domain, id] = pathname.match(statusRegex) || [];
for (const regex of statusPostRegexes) {
const [, id] = pathname.match(regex) || [];
console.log(pathname, regex, id);
if (id) {
return {
instance: hostname,
id,
};
}
}
return {};
}

const [, noteId] = pathname.match(statusNoteRegex) || [];

if (noteId) {
return `/${hostname}/s/${noteId}`;
function getInstanceStatusURL(url) {
const { instance, id } = getInstanceStatusObject(url);
if (instance && id) {
return `/${instance}/s/${id}`;
}
return null;
}

export default getInstanceStatusURL;
export default getInstanceStatusURL;

0 comments on commit 154e7e9

Please sign in to comment.