mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import {useState, useEffect} from 'react'
2import {useStores} from 'state/index'
3import {ImageModel} from 'state/models/media/image'
4import * as apilib from 'lib/api/index'
5import {getLinkMeta} from 'lib/link-meta/link-meta'
6import {
7 getPostAsQuote,
8 getFeedAsEmbed,
9 getListAsEmbed,
10} from 'lib/link-meta/bsky'
11import {downloadAndResize} from 'lib/media/manip'
12import {
13 isBskyPostUrl,
14 isBskyCustomFeedUrl,
15 isBskyListUrl,
16} from 'lib/strings/url-helpers'
17import {ComposerOpts} from 'state/models/ui/shell'
18import {POST_IMG_MAX} from 'lib/constants'
19
20export function useExternalLinkFetch({
21 setQuote,
22}: {
23 setQuote: (opts: ComposerOpts['quote']) => void
24}) {
25 const store = useStores()
26 const [extLink, setExtLink] = useState<apilib.ExternalEmbedDraft | undefined>(
27 undefined,
28 )
29
30 useEffect(() => {
31 let aborted = false
32 const cleanup = () => {
33 aborted = true
34 }
35 if (!extLink) {
36 return cleanup
37 }
38 if (!extLink.meta) {
39 if (isBskyPostUrl(extLink.uri)) {
40 getPostAsQuote(store, extLink.uri).then(
41 newQuote => {
42 if (aborted) {
43 return
44 }
45 setQuote(newQuote)
46 setExtLink(undefined)
47 },
48 err => {
49 store.log.error('Failed to fetch post for quote embedding', {err})
50 setExtLink(undefined)
51 },
52 )
53 } else if (isBskyCustomFeedUrl(extLink.uri)) {
54 getFeedAsEmbed(store, extLink.uri).then(
55 ({embed, meta}) => {
56 if (aborted) {
57 return
58 }
59 setExtLink({
60 uri: extLink.uri,
61 isLoading: false,
62 meta,
63 embed,
64 })
65 },
66 err => {
67 store.log.error('Failed to fetch feed for embedding', {err})
68 setExtLink(undefined)
69 },
70 )
71 } else if (isBskyListUrl(extLink.uri)) {
72 getListAsEmbed(store, extLink.uri).then(
73 ({embed, meta}) => {
74 if (aborted) {
75 return
76 }
77 setExtLink({
78 uri: extLink.uri,
79 isLoading: false,
80 meta,
81 embed,
82 })
83 },
84 err => {
85 store.log.error('Failed to fetch list for embedding', {err})
86 setExtLink(undefined)
87 },
88 )
89 } else {
90 getLinkMeta(store, extLink.uri).then(meta => {
91 if (aborted) {
92 return
93 }
94 setExtLink({
95 uri: extLink.uri,
96 isLoading: !!meta.image,
97 meta,
98 })
99 })
100 }
101 return cleanup
102 }
103 if (extLink.isLoading && extLink.meta?.image && !extLink.localThumb) {
104 downloadAndResize({
105 uri: extLink.meta.image,
106 width: POST_IMG_MAX.width,
107 height: POST_IMG_MAX.height,
108 mode: 'contain',
109 maxSize: POST_IMG_MAX.size,
110 timeout: 15e3,
111 })
112 .catch(() => undefined)
113 .then(localThumb => {
114 if (aborted) {
115 return
116 }
117 setExtLink({
118 ...extLink,
119 isLoading: false, // done
120 localThumb: localThumb
121 ? new ImageModel(store, localThumb)
122 : undefined,
123 })
124 })
125 return cleanup
126 }
127 if (extLink.isLoading) {
128 setExtLink({
129 ...extLink,
130 isLoading: false, // done
131 })
132 }
133 return cleanup
134 }, [store, extLink, setQuote])
135
136 return {extLink, setExtLink}
137}