add handling of app links on search #8

merged
opened by aylac.top targeting main from aylac.top/pdsls: apphandling

adds handling of links for some (the same that are in the templates.ts file) atproto apps

it lets you paste links like https://tangled.org/@pdsls.dev/pdsls and it will convert it to the at:// link

unfortunately doesn't work with links that don't provide all the necessary information to get the record (like the links for issues on tangled)

if it detects a link on the search it will try seeing if it has an app that matches it and then runs a function to handle it

it uses an enum for the apps thing because i thought it would look cool, but can easily be replaced with strings if that's preferred

really hope i didn't mess anything up

Changed files
+112
src
utils
+112
src/utils/app-urls.ts
··· 1 + export type AppUrl = `${string}.${string}` | `localhost:${number}`; 2 + type AppUrlObject = Record<AppUrl, App>; 3 + type AppHandleLinkObject = Record<App, (url: string[]) => string>; 4 + 5 + export enum App { 6 + Bluesky = 0, 7 + Tangled = 1, 8 + Whitewind = 2, 9 + Frontpage = 3, 10 + Pinksea = 4, 11 + Linkat = 5, 12 + } 13 + 14 + export const appList: AppUrlObject = { 15 + "localhost:19006": App.Bluesky, 16 + "blacksky.community": App.Bluesky, 17 + "bsky.app": App.Bluesky, 18 + "catsky.social": App.Bluesky, 19 + "deer.aylac.top": App.Bluesky, 20 + "deer-social-ayla.pages.dev": App.Bluesky, 21 + "deer.social": App.Bluesky, 22 + "main.bsky.dev": App.Bluesky, 23 + "social.daniela.lol": App.Bluesky, 24 + "tangled.org": App.Tangled, 25 + "whtwnd.com": App.Whitewind, 26 + "frontpage.fyi": App.Frontpage, 27 + "pinksea.art": App.Pinksea, 28 + "linkat.blue": App.Linkat, 29 + }; 30 + 31 + export const appHandleLink: AppHandleLinkObject = { 32 + [App.Bluesky]: (path) => { 33 + const baseType = path[0]; 34 + const user = path[1]; 35 + 36 + if (baseType === "profile") { 37 + if (path[2]) { 38 + const type = path[2]; 39 + const rkey = path[3]; 40 + 41 + if (type === "post") { 42 + return `at://${user}/app.bsky.feed.post/${rkey}`; 43 + } else if (type === "list") { 44 + return `at://${user}/app.bsky.graph.list/${rkey}`; 45 + } else if (type === "feed") { 46 + return `at://${user}/app.bsky.feed.generator/${rkey}`; 47 + } else if (type === "follows") { 48 + return `at://${user}/app.bsky.graph.follow/${rkey}`; 49 + } 50 + } else { 51 + return `at://${user}`; 52 + } 53 + } else if (baseType === "starter-pack") { 54 + return `at://${user}/app.bsky.graph.starterpack/${path[2]}`; 55 + } 56 + return `at://${user}`; 57 + }, 58 + [App.Tangled]: (path) => { 59 + if (path[0] === "strings") { 60 + return `at://${path[1]}/sh.tangled.string/${path[2]}`; 61 + } 62 + 63 + let query: string | undefined; 64 + if (path[path.length - 1].includes("?")) { 65 + const split = path[path.length - 1].split("?"); 66 + query = split[1]; 67 + path[path.length - 1] = split[0]; 68 + } 69 + 70 + const user = path[0].replace("@", ""); 71 + 72 + if (path.length === 1) { 73 + if (query === "tab=repos") { 74 + return `at://${user}/sh.tangled.repo`; 75 + } else if (query === "tab=starred") { 76 + return `at://${user}/sh.tangled.feed.star`; 77 + } else if (query === "tab=strings") { 78 + return `at://${user}/sh.tangled.string`; 79 + } 80 + } else if (path.length === 2) { 81 + // no way to convert the repo name to an rkey afaik 82 + // same reason why there's nothing related to issues in here 83 + return `at://${user}/sh.tangled.repo`; 84 + } 85 + 86 + return `at://${user}`; 87 + }, 88 + [App.Whitewind]: (path) => { 89 + if (path.length === 2) { 90 + return `at://${path[0]}/com.whtwnd.blog.entry/${path[1]}`; 91 + } 92 + 93 + return `at://${path[0]}/com.whtwnd.blog.entry`; 94 + }, 95 + [App.Frontpage]: (path) => { 96 + if (path.length === 3) { 97 + return `at://${path[1]}/fyi.unravel.frontpage.post/${path[2]}`; 98 + } else if (path.length === 5) { 99 + return `at://${path[3]}/fyi.unravel.frontpage.comment/${path[4]}`; 100 + } 101 + 102 + return `at://${path[0]}`; 103 + }, 104 + [App.Pinksea]: (path) => { 105 + if (path.length === 2) { 106 + return `at://${path[0]}/com.shinolabs.pinksea.oekaki/${path[1]}`; 107 + } 108 + 109 + return `at://${path[0]}`; 110 + }, 111 + [App.Linkat]: (path) => `at://${path[0]}/blue.linkat.board/self`, 112 + };