@streamplace/components 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,41 +6,62 @@ import { LivestreamViewHydrated } from "streamplace/src/useful-types";
6
6
  import { useUrl } from "./streamplace-store";
7
7
  import { usePDSAgent } from "./xrpc";
8
8
 
9
- const uploadThumbnail = async (
10
- pdsAgent: StreamplaceAgent,
11
- customThumbnail?: Blob,
12
- ) => {
13
- if (customThumbnail) {
14
- let tries = 0;
15
- try {
16
- let thumbnail = await pdsAgent.uploadBlob(customThumbnail);
17
-
18
- while (
19
- thumbnail.data.blob.size === 0 &&
20
- customThumbnail.size !== 0 &&
21
- tries < 3
22
- ) {
23
- console.warn(
24
- "Reuploading blob as blob sizes don't match! Blob size recieved is",
25
- thumbnail.data.blob.size,
26
- "and sent blob size is",
27
- customThumbnail.size,
28
- );
29
- thumbnail = await pdsAgent.uploadBlob(customThumbnail);
30
- }
9
+ import { useEffect, useRef } from "react";
31
10
 
32
- if (tries === 3) {
33
- throw new Error("Could not successfully upload blob (tried thrice)");
34
- }
11
+ const useUploadThumbnail = () => {
12
+ const abortRef = useRef<AbortController | null>(null);
13
+
14
+ useEffect(() => {
15
+ return () => {
16
+ // On unmount, abort any ongoing upload
17
+ abortRef.current?.abort();
18
+ };
19
+ }, []);
20
+
21
+ const uploadThumbnail = async (
22
+ pdsAgent: StreamplaceAgent,
23
+ customThumbnail?: Blob,
24
+ ) => {
25
+ if (!customThumbnail) return undefined;
26
+
27
+ abortRef.current = new AbortController();
28
+ const { signal } = abortRef.current;
29
+
30
+ const maxTries = 3;
31
+ let lastError: unknown = null;
35
32
 
36
- if (thumbnail.success) {
37
- console.log("Successfully uploaded thumbnail");
38
- return thumbnail.data.blob;
33
+ for (let tries = 0; tries < maxTries; tries++) {
34
+ try {
35
+ const thumbnail = await pdsAgent.uploadBlob(customThumbnail, {
36
+ signal,
37
+ });
38
+ if (
39
+ thumbnail.success &&
40
+ thumbnail.data.blob.size === customThumbnail.size
41
+ ) {
42
+ console.log("Successfully uploaded thumbnail");
43
+ return thumbnail.data.blob;
44
+ } else {
45
+ console.warn(
46
+ `Blob size mismatch (attempt ${tries + 1}): received ${thumbnail.data.blob.size}, expected ${customThumbnail.size}`,
47
+ );
48
+ }
49
+ } catch (e) {
50
+ if (signal.aborted) {
51
+ console.warn("Upload aborted");
52
+ return undefined;
53
+ }
54
+ lastError = e;
55
+ console.warn(`Error uploading thumbnail (attempt ${tries + 1}): ${e}`);
39
56
  }
40
- } catch (e) {
41
- throw new Error("Error uploading thumbnail: " + e);
42
57
  }
43
- }
58
+
59
+ throw new Error(
60
+ `Could not successfully upload blob after ${maxTries} attempts. Last error: ${lastError}`,
61
+ );
62
+ };
63
+
64
+ return uploadThumbnail;
44
65
  };
45
66
 
46
67
  async function createNewPost(
@@ -57,13 +78,14 @@ async function createNewPost(
57
78
  }
58
79
  }
59
80
 
60
- function buildGoLivePost(
81
+ async function buildGoLivePost(
61
82
  text: string,
62
83
  url: URL,
63
84
  profile: ProfileViewDetailed,
64
85
  params: URLSearchParams,
65
86
  thumbnail: BlobRef | undefined,
66
- ): AppBskyFeedPost.Record {
87
+ agent: StreamplaceAgent,
88
+ ): Promise<AppBskyFeedPost.Record> {
67
89
  const now = new Date();
68
90
  const linkUrl = `${url.protocol}//${url.host}/${profile.handle}?${params.toString()}`;
69
91
  const prefix = `🔴 LIVE `;
@@ -72,7 +94,7 @@ function buildGoLivePost(
72
94
  const content = prefix + textUrl + suffix;
73
95
 
74
96
  const rt = new RichText({ text: content });
75
- rt.detectFacetsWithoutResolution();
97
+ await rt.detectFacets(agent);
76
98
  const record: AppBskyFeedPost.Record = {
77
99
  $type: "app.bsky.feed.post",
78
100
  text: content,
@@ -99,6 +121,7 @@ function buildGoLivePost(
99
121
  export function useCreateStreamRecord() {
100
122
  let agent = usePDSAgent();
101
123
  let url = useUrl();
124
+ const uploadThumbnail = useUploadThumbnail();
102
125
 
103
126
  return async (
104
127
  title: string,
@@ -175,7 +198,14 @@ export function useCreateStreamRecord() {
175
198
  time: new Date().toISOString(),
176
199
  });
177
200
 
178
- let post = buildGoLivePost(title, u, profile.data, params, thumbnail);
201
+ let post = await buildGoLivePost(
202
+ title,
203
+ u,
204
+ profile.data,
205
+ params,
206
+ thumbnail,
207
+ agent,
208
+ );
179
209
 
180
210
  newPost = await createNewPost(agent, post);
181
211
 
@@ -206,6 +236,7 @@ export function useCreateStreamRecord() {
206
236
  export function useUpdateStreamRecord() {
207
237
  let agent = usePDSAgent();
208
238
  let url = useUrl();
239
+ const uploadThumbnail = useUploadThumbnail();
209
240
 
210
241
  return async (
211
242
  title: string,