@streamplace/components 0.7.2 → 0.7.7
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.
- package/dist/components/chat/chat-box.js +212 -24
- package/dist/components/chat/chat-message.js +5 -5
- package/dist/components/chat/chat.js +83 -5
- package/dist/components/chat/emoji-suggestions.js +35 -0
- package/dist/components/chat/mod-view.js +59 -8
- package/dist/components/chat/system-message.js +19 -0
- package/dist/components/icons/bluesky-icon.js +9 -0
- package/dist/components/keep-awake.js +7 -0
- package/dist/components/keep-awake.native.js +16 -0
- package/dist/components/mobile-player/fullscreen.js +2 -1
- package/dist/components/mobile-player/fullscreen.native.js +3 -3
- package/dist/components/mobile-player/player.js +15 -30
- package/dist/components/mobile-player/ui/index.js +2 -0
- package/dist/components/mobile-player/ui/report-modal.js +90 -0
- package/dist/components/mobile-player/ui/streamer-loading-overlay.js +104 -0
- package/dist/components/mobile-player/ui/viewer-context-menu.js +20 -1
- package/dist/components/mobile-player/ui/viewer-loading-overlay.js +49 -0
- package/dist/components/mobile-player/use-webrtc.js +7 -1
- package/dist/components/mobile-player/video-retry.js +29 -0
- package/dist/components/mobile-player/video.js +84 -9
- package/dist/components/mobile-player/video.native.js +24 -10
- package/dist/components/share/sharesheet.js +91 -0
- package/dist/components/ui/dialog.js +1 -1
- package/dist/components/ui/dropdown.js +6 -6
- package/dist/components/ui/index.js +2 -0
- package/dist/components/ui/primitives/modal.js +0 -1
- package/dist/components/ui/resizeable.js +20 -11
- package/dist/components/ui/slider.js +5 -0
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/usePointerDevice.js +71 -0
- package/dist/index.js +10 -3
- package/dist/lib/system-messages.js +101 -0
- package/dist/livestream-store/chat.js +111 -18
- package/dist/livestream-store/livestream-store.js +3 -0
- package/dist/livestream-store/problems.js +76 -0
- package/dist/livestream-store/websocket-consumer.js +39 -4
- package/dist/player-store/player-store.js +33 -4
- package/dist/streamplace-store/block.js +51 -12
- package/dist/streamplace-store/stream.js +44 -23
- package/dist/ui/index.js +79 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/56540125 +0 -0
- package/node-compile-cache/{v22.15.0-x64-92db9086-0 → v22.15.0-x64-efe9a9df-0}/67b1eb60 +0 -0
- package/node-compile-cache/{v22.15.0-x64-92db9086-0 → v22.15.0-x64-efe9a9df-0}/7c275f90 +0 -0
- package/package.json +6 -2
- package/src/components/chat/chat-box.tsx +295 -25
- package/src/components/chat/chat-message.tsx +6 -7
- package/src/components/chat/chat.tsx +192 -41
- package/src/components/chat/emoji-suggestions.tsx +94 -0
- package/src/components/chat/mod-view.tsx +119 -40
- package/src/components/chat/system-message.tsx +38 -0
- package/src/components/icons/bluesky-icon.tsx +9 -0
- package/src/components/keep-awake.native.tsx +13 -0
- package/src/components/keep-awake.tsx +3 -0
- package/src/components/mobile-player/fullscreen.native.tsx +12 -3
- package/src/components/mobile-player/fullscreen.tsx +10 -3
- package/src/components/mobile-player/player.tsx +28 -36
- package/src/components/mobile-player/props.tsx +1 -0
- package/src/components/mobile-player/ui/index.ts +2 -0
- package/src/components/mobile-player/ui/report-modal.tsx +195 -0
- package/src/components/mobile-player/ui/streamer-loading-overlay.tsx +154 -0
- package/src/components/mobile-player/ui/viewer-context-menu.tsx +31 -3
- package/src/components/mobile-player/ui/viewer-loading-overlay.tsx +66 -0
- package/src/components/mobile-player/use-webrtc.tsx +10 -2
- package/src/components/mobile-player/video-retry.tsx +28 -0
- package/src/components/mobile-player/video.native.tsx +24 -10
- package/src/components/mobile-player/video.tsx +100 -21
- package/src/components/share/sharesheet.tsx +185 -0
- package/src/components/ui/dialog.tsx +1 -1
- package/src/components/ui/dropdown.tsx +13 -13
- package/src/components/ui/index.ts +2 -0
- package/src/components/ui/primitives/modal.tsx +0 -1
- package/src/components/ui/resizeable.tsx +26 -15
- package/src/components/ui/slider.tsx +1 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/usePointerDevice.ts +89 -0
- package/src/index.tsx +11 -2
- package/src/lib/system-messages.ts +135 -0
- package/src/livestream-store/chat.tsx +145 -17
- package/src/livestream-store/livestream-state.tsx +10 -0
- package/src/livestream-store/livestream-store.tsx +3 -0
- package/src/livestream-store/problems.tsx +96 -0
- package/src/livestream-store/websocket-consumer.tsx +44 -4
- package/src/player-store/player-state.tsx +25 -4
- package/src/player-store/player-store.tsx +43 -5
- package/src/streamplace-store/block.tsx +55 -13
- package/src/streamplace-store/stream.tsx +66 -35
- package/src/ui/index.ts +86 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/node-compile-cache/v22.15.0-x64-92db9086-0/37be0eec +0 -0
- package/node-compile-cache/v22.15.0-x64-92db9086-0/56540125 +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ComAtprotoModerationCreateReport } from "@atproto/api";
|
|
1
2
|
import { ChatMessageViewHydrated } from "streamplace";
|
|
2
3
|
|
|
3
4
|
export enum PlayerProtocol {
|
|
@@ -99,10 +100,6 @@ export interface PlayerState {
|
|
|
99
100
|
setPlayTime: (playTime: number) => void;
|
|
100
101
|
|
|
101
102
|
/** Flag indicating if player is in offline state */
|
|
102
|
-
offline: boolean;
|
|
103
|
-
|
|
104
|
-
/** Function to set the offline state */
|
|
105
|
-
setOffline: (offline: boolean) => void;
|
|
106
103
|
/** Reference to the video element for direct manipulation (used for PiP) */
|
|
107
104
|
videoRef:
|
|
108
105
|
| React.MutableRefObject<HTMLVideoElement | null>
|
|
@@ -119,6 +116,10 @@ export interface PlayerState {
|
|
|
119
116
|
| undefined,
|
|
120
117
|
) => void;
|
|
121
118
|
|
|
119
|
+
pipAction: (() => void) | undefined;
|
|
120
|
+
/** Function to set the Picture-in-Picture action */
|
|
121
|
+
setPipAction: (action: (() => void) | undefined) => void;
|
|
122
|
+
|
|
122
123
|
/** Player element width (CSS value or number) */
|
|
123
124
|
playerWidth?: string | number;
|
|
124
125
|
/** Function to set the player width */
|
|
@@ -176,6 +177,26 @@ export interface PlayerState {
|
|
|
176
177
|
|
|
177
178
|
/** Function to set the mod message */
|
|
178
179
|
setModMessage: (message: ChatMessageViewHydrated | null) => void;
|
|
180
|
+
|
|
181
|
+
/** URL to send player events to (if not default) */
|
|
182
|
+
reportingURL: string | null;
|
|
183
|
+
|
|
184
|
+
/** Function to set the reporting URL */
|
|
185
|
+
setReportingURL: (reportingURL: string | null) => void;
|
|
186
|
+
|
|
187
|
+
/** Is the report modal open? */
|
|
188
|
+
reportModalOpen: boolean;
|
|
189
|
+
|
|
190
|
+
/** Function to set the report modal open state */
|
|
191
|
+
setReportModalOpen: (reportModalOpen: boolean) => void;
|
|
192
|
+
|
|
193
|
+
/** Subject to report */
|
|
194
|
+
reportSubject: ComAtprotoModerationCreateReport.InputSchema["subject"] | null;
|
|
195
|
+
|
|
196
|
+
/** Function to set the report subject */
|
|
197
|
+
setReportSubject: (
|
|
198
|
+
subject: ComAtprotoModerationCreateReport.InputSchema["subject"] | null,
|
|
199
|
+
) => void;
|
|
179
200
|
}
|
|
180
201
|
|
|
181
202
|
export type PlayerEvent = {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ComAtprotoModerationCreateReport } from "@atproto/api";
|
|
2
|
+
import { useContext, useEffect, useState } from "react";
|
|
2
3
|
import { ChatMessageViewHydrated } from "streamplace";
|
|
3
4
|
import { createStore, StoreApi, useStore } from "zustand";
|
|
5
|
+
import { useLivestreamStore } from "../livestream-store";
|
|
4
6
|
import { PlayerContext } from "./context";
|
|
5
7
|
import {
|
|
6
8
|
IngestMediaSource,
|
|
@@ -68,9 +70,6 @@ export const makePlayerStore = (id?: string): StoreApi<PlayerState> => {
|
|
|
68
70
|
playTime: 0,
|
|
69
71
|
setPlayTime: (playTime: number) => set(() => ({ playTime })),
|
|
70
72
|
|
|
71
|
-
offline: false,
|
|
72
|
-
setOffline: (offline: boolean) => set(() => ({ offline })),
|
|
73
|
-
|
|
74
73
|
videoRef: undefined,
|
|
75
74
|
setVideoRef: (
|
|
76
75
|
videoRef:
|
|
@@ -83,6 +82,11 @@ export const makePlayerStore = (id?: string): StoreApi<PlayerState> => {
|
|
|
83
82
|
pipMode: false,
|
|
84
83
|
setPipMode: (pipMode: boolean) => set(() => ({ pipMode })),
|
|
85
84
|
|
|
85
|
+
// Picture-in-Picture action function (set by player component)
|
|
86
|
+
pipAction: undefined,
|
|
87
|
+
setPipAction: (action: (() => void) | undefined) =>
|
|
88
|
+
set(() => ({ pipAction: action })),
|
|
89
|
+
|
|
86
90
|
// Player element width/height setters for global sync
|
|
87
91
|
playerWidth: undefined,
|
|
88
92
|
setPlayerWidth: (playerWidth: number) => set(() => ({ playerWidth })),
|
|
@@ -109,6 +113,10 @@ export const makePlayerStore = (id?: string): StoreApi<PlayerState> => {
|
|
|
109
113
|
ingestLive: false,
|
|
110
114
|
setIngestLive: (ingestLive: boolean) => set(() => ({ ingestLive })),
|
|
111
115
|
|
|
116
|
+
reportingURL: null,
|
|
117
|
+
setReportingURL: (reportingURL: string | null) =>
|
|
118
|
+
set(() => ({ reportingURL })),
|
|
119
|
+
|
|
112
120
|
playerEvent: async (
|
|
113
121
|
url: string,
|
|
114
122
|
time: string,
|
|
@@ -126,7 +134,8 @@ export const makePlayerStore = (id?: string): StoreApi<PlayerState> => {
|
|
|
126
134
|
};
|
|
127
135
|
try {
|
|
128
136
|
// fetch url from sp provider
|
|
129
|
-
|
|
137
|
+
const reportingURL = x.reportingURL ?? `${url}/api/player-event`;
|
|
138
|
+
fetch(reportingURL, {
|
|
130
139
|
method: "POST",
|
|
131
140
|
body: JSON.stringify(data),
|
|
132
141
|
});
|
|
@@ -163,6 +172,15 @@ export const makePlayerStore = (id?: string): StoreApi<PlayerState> => {
|
|
|
163
172
|
modMessage: null,
|
|
164
173
|
setModMessage: (modMessage: ChatMessageViewHydrated | null) =>
|
|
165
174
|
set(() => ({ modMessage })),
|
|
175
|
+
|
|
176
|
+
reportModalOpen: false,
|
|
177
|
+
setReportModalOpen: (reportModalOpen: boolean) =>
|
|
178
|
+
set(() => ({ reportModalOpen })),
|
|
179
|
+
|
|
180
|
+
reportSubject: null,
|
|
181
|
+
setReportSubject: (
|
|
182
|
+
subject: ComAtprotoModerationCreateReport.InputSchema["subject"] | null,
|
|
183
|
+
) => set(() => ({ reportSubject: subject })),
|
|
166
184
|
}));
|
|
167
185
|
};
|
|
168
186
|
|
|
@@ -237,3 +255,23 @@ export const intoPlayerProtocol = (protocol: string): PlayerProtocol => {
|
|
|
237
255
|
return PlayerProtocol.WEBRTC;
|
|
238
256
|
}
|
|
239
257
|
};
|
|
258
|
+
|
|
259
|
+
// returns true if the livestream has been offline for more than 10 seconds and we're not playing
|
|
260
|
+
export const useOffline = () => {
|
|
261
|
+
const status = usePlayerStore((x) => x.status);
|
|
262
|
+
const segment = useLivestreamStore((x) => x.segment);
|
|
263
|
+
const [now, setNow] = useState(Date.now());
|
|
264
|
+
useEffect(() => {
|
|
265
|
+
const interval = setInterval(() => {
|
|
266
|
+
setNow(Date.now());
|
|
267
|
+
}, 500);
|
|
268
|
+
return () => clearInterval(interval);
|
|
269
|
+
}, []);
|
|
270
|
+
if (status === PlayerStatus.PLAYING) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
if (!segment?.startTime) {
|
|
274
|
+
return false;
|
|
275
|
+
}
|
|
276
|
+
return now - Date.parse(segment.startTime) > 10000;
|
|
277
|
+
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { AppBskyGraphBlock } from "@atproto/api";
|
|
2
|
+
import { useState } from "react";
|
|
2
3
|
import { usePDSAgent } from "./xrpc";
|
|
3
4
|
|
|
4
5
|
export function useCreateBlockRecord() {
|
|
5
6
|
let agent = usePDSAgent();
|
|
7
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
const createBlock = async (subjectDID: string) => {
|
|
8
10
|
if (!agent) {
|
|
9
11
|
throw new Error("No PDS agent found");
|
|
10
12
|
}
|
|
@@ -13,17 +15,57 @@ export function useCreateBlockRecord() {
|
|
|
13
15
|
throw new Error("No user DID found, assuming not logged in");
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
setIsLoading(true);
|
|
19
|
+
try {
|
|
20
|
+
const record: AppBskyGraphBlock.Record = {
|
|
21
|
+
$type: "app.bsky.graph.block",
|
|
22
|
+
subject: subjectDID,
|
|
23
|
+
createdAt: new Date().toISOString(),
|
|
24
|
+
};
|
|
25
|
+
const result = await agent.com.atproto.repo.createRecord({
|
|
26
|
+
repo: agent.did,
|
|
27
|
+
collection: "app.bsky.graph.block",
|
|
28
|
+
record,
|
|
29
|
+
});
|
|
30
|
+
return result;
|
|
31
|
+
} finally {
|
|
32
|
+
setIsLoading(false);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return { createBlock, isLoading };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function useCreateHideChatRecord() {
|
|
40
|
+
let agent = usePDSAgent();
|
|
41
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
42
|
+
|
|
43
|
+
const createHideChat = async (chatMessageUri: string) => {
|
|
44
|
+
if (!agent) {
|
|
45
|
+
throw new Error("No PDS agent found");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!agent.did) {
|
|
49
|
+
throw new Error("No user DID found, assuming not logged in");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
setIsLoading(true);
|
|
53
|
+
try {
|
|
54
|
+
const record = {
|
|
55
|
+
$type: "place.stream.chat.gate",
|
|
56
|
+
hiddenMessage: chatMessageUri,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const result = await agent.com.atproto.repo.createRecord({
|
|
60
|
+
repo: agent.did,
|
|
61
|
+
collection: "place.stream.chat.gate",
|
|
62
|
+
record,
|
|
63
|
+
});
|
|
64
|
+
return result;
|
|
65
|
+
} finally {
|
|
66
|
+
setIsLoading(false);
|
|
67
|
+
}
|
|
28
68
|
};
|
|
69
|
+
|
|
70
|
+
return { createHideChat, isLoading };
|
|
29
71
|
}
|
|
@@ -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
|
-
|
|
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
|
-
|
|
33
|
-
|
|
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
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
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.
|
|
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(
|
|
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,
|
package/src/ui/index.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @streamplace/components/ui - Streamplace ZeroCSS
|
|
3
|
+
*
|
|
4
|
+
* Clean export path for ZeroCSS styling utilities, design tokens, and atomic styles.
|
|
5
|
+
* ZeroCSS provides a zero-config, atomic styling system optimized for React Native.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// Export the most commonly used ZeroCSS utilities
|
|
9
|
+
export {
|
|
10
|
+
// Core atoms object
|
|
11
|
+
atoms,
|
|
12
|
+
// Common shorthand utilities
|
|
13
|
+
bg,
|
|
14
|
+
// Border utilities
|
|
15
|
+
borders,
|
|
16
|
+
bottom,
|
|
17
|
+
// Flex utilities
|
|
18
|
+
flex,
|
|
19
|
+
// Gap utilities (React Native 0.71+)
|
|
20
|
+
gap,
|
|
21
|
+
h,
|
|
22
|
+
// Layout utilities
|
|
23
|
+
layout,
|
|
24
|
+
left,
|
|
25
|
+
m,
|
|
26
|
+
mb,
|
|
27
|
+
ml,
|
|
28
|
+
mr,
|
|
29
|
+
mt,
|
|
30
|
+
mx,
|
|
31
|
+
my,
|
|
32
|
+
p,
|
|
33
|
+
pb,
|
|
34
|
+
pl,
|
|
35
|
+
// Position utilities
|
|
36
|
+
position,
|
|
37
|
+
pr,
|
|
38
|
+
pt,
|
|
39
|
+
px,
|
|
40
|
+
py,
|
|
41
|
+
r,
|
|
42
|
+
right,
|
|
43
|
+
text,
|
|
44
|
+
top,
|
|
45
|
+
w,
|
|
46
|
+
} from "../lib/theme/atoms";
|
|
47
|
+
|
|
48
|
+
// Export ZeroCSS design tokens
|
|
49
|
+
export {
|
|
50
|
+
borderRadius,
|
|
51
|
+
breakpoints,
|
|
52
|
+
colors,
|
|
53
|
+
shadows,
|
|
54
|
+
spacing,
|
|
55
|
+
typography,
|
|
56
|
+
} from "../lib/theme/tokens";
|
|
57
|
+
|
|
58
|
+
// Export ZeroCSS utility functions
|
|
59
|
+
export {
|
|
60
|
+
debounce,
|
|
61
|
+
mergeStyles,
|
|
62
|
+
platformStyle,
|
|
63
|
+
responsiveValue,
|
|
64
|
+
} from "../lib/utils";
|
|
65
|
+
|
|
66
|
+
// Export ZeroCSS theme system
|
|
67
|
+
export {
|
|
68
|
+
ThemeProvider,
|
|
69
|
+
createThemeColors,
|
|
70
|
+
createThemeIcons,
|
|
71
|
+
createThemeStyles,
|
|
72
|
+
createThemedStyles,
|
|
73
|
+
darkTheme,
|
|
74
|
+
lightTheme,
|
|
75
|
+
usePlatformTypography,
|
|
76
|
+
useTheme,
|
|
77
|
+
type Theme,
|
|
78
|
+
type ThemeIcons,
|
|
79
|
+
type ThemeStyles,
|
|
80
|
+
} from "../lib/theme/theme";
|
|
81
|
+
|
|
82
|
+
// Namespace exports for power users
|
|
83
|
+
export * as theme from "../lib/theme";
|
|
84
|
+
export * as atomsNS from "../lib/theme/atoms";
|
|
85
|
+
export * as tokens from "../lib/theme/tokens";
|
|
86
|
+
export * as utils from "../lib/utils";
|