@streamplace/components 0.9.1 → 0.9.6
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/mod-view.d.ts.map +1 -1
- package/dist/components/chat/mod-view.js +8 -88
- package/dist/components/chat/mod-view.js.map +1 -1
- package/dist/components/chat/update-stream-title-dialog.d.ts +9 -0
- package/dist/components/chat/update-stream-title-dialog.d.ts.map +1 -0
- package/dist/components/chat/update-stream-title-dialog.js +74 -0
- package/dist/components/chat/update-stream-title-dialog.js.map +1 -0
- package/dist/components/content-metadata/content-metadata-form.d.ts.map +1 -1
- package/dist/components/content-metadata/content-metadata-form.js +7 -8
- package/dist/components/content-metadata/content-metadata-form.js.map +1 -1
- package/dist/components/mobile-player/ui/report-modal.d.ts.map +1 -1
- package/dist/components/mobile-player/ui/report-modal.js +1 -1
- package/dist/components/mobile-player/ui/report-modal.js.map +1 -1
- package/dist/components/mobile-player/ui/viewer-loading-overlay.d.ts.map +1 -1
- package/dist/components/mobile-player/ui/viewer-loading-overlay.js +0 -1
- package/dist/components/mobile-player/ui/viewer-loading-overlay.js.map +1 -1
- package/dist/components/ui/admonition.d.ts +14 -0
- package/dist/components/ui/admonition.d.ts.map +1 -0
- package/dist/components/ui/admonition.js +117 -0
- package/dist/components/ui/admonition.js.map +1 -0
- package/dist/components/ui/button.d.ts +1 -0
- package/dist/components/ui/button.d.ts.map +1 -1
- package/dist/components/ui/button.js +2 -2
- package/dist/components/ui/button.js.map +1 -1
- package/dist/components/ui/index.d.ts +1 -0
- package/dist/components/ui/index.d.ts.map +1 -1
- package/dist/components/ui/index.js +1 -0
- package/dist/components/ui/index.js.map +1 -1
- package/dist/components/ui/primitives/button.d.ts +3 -2
- package/dist/components/ui/primitives/button.d.ts.map +1 -1
- package/dist/components/ui/primitives/button.js +20 -2
- package/dist/components/ui/primitives/button.js.map +1 -1
- package/dist/components/ui/resizeable.d.ts.map +1 -1
- package/dist/components/ui/resizeable.js +2 -1
- package/dist/components/ui/resizeable.js.map +1 -1
- package/dist/components/ui/text.d.ts +2 -1
- package/dist/components/ui/text.d.ts.map +1 -1
- package/dist/components/ui/text.js.map +1 -1
- package/dist/components/ui/textarea.d.ts.map +1 -1
- package/dist/components/ui/textarea.js +3 -1
- package/dist/components/ui/textarea.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/theme/atoms.d.ts +148 -148
- package/dist/lib/theme/tokens.d.ts +11 -11
- package/dist/lib/theme/tokens.js +11 -11
- package/dist/utils/did.d.ts +13 -0
- package/dist/utils/did.d.ts.map +1 -0
- package/dist/utils/did.js +43 -0
- package/dist/utils/did.js.map +1 -0
- package/locales/en-US/settings.ftl +2 -1
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/package.json +2 -2
- package/src/components/chat/mod-view.tsx +2 -218
- package/src/components/chat/update-stream-title-dialog.tsx +169 -0
- package/src/components/content-metadata/content-metadata-form.tsx +37 -10
- package/src/components/mobile-player/ui/report-modal.tsx +2 -0
- package/src/components/mobile-player/ui/viewer-loading-overlay.tsx +0 -1
- package/src/components/ui/admonition.tsx +177 -0
- package/src/components/ui/button.tsx +3 -0
- package/src/components/ui/index.ts +1 -0
- package/src/components/ui/primitives/button.tsx +37 -11
- package/src/components/ui/resizeable.tsx +2 -1
- package/src/components/ui/text.tsx +11 -1
- package/src/components/ui/textarea.tsx +3 -0
- package/src/index.tsx +2 -0
- package/src/lib/theme/tokens.ts +11 -11
- package/src/utils/did.ts +61 -0
|
@@ -329,17 +329,17 @@ export declare const colors: {
|
|
|
329
329
|
readonly 950: "#052e16";
|
|
330
330
|
};
|
|
331
331
|
readonly warning: {
|
|
332
|
-
readonly 50: "#
|
|
333
|
-
readonly 100: "#
|
|
334
|
-
readonly 200: "#
|
|
335
|
-
readonly 300: "#
|
|
336
|
-
readonly 400: "#
|
|
337
|
-
readonly 500: "#
|
|
338
|
-
readonly 600: "#
|
|
339
|
-
readonly 700: "#
|
|
340
|
-
readonly 800: "#
|
|
341
|
-
readonly 900: "#
|
|
342
|
-
readonly 950: "#
|
|
332
|
+
readonly 50: "#fffaf0";
|
|
333
|
+
readonly 100: "#ffe6c7";
|
|
334
|
+
readonly 200: "#ffd99e";
|
|
335
|
+
readonly 300: "#ffcc75";
|
|
336
|
+
readonly 400: "#ffb94e";
|
|
337
|
+
readonly 500: "#ff9e1f";
|
|
338
|
+
readonly 600: "#e67e00";
|
|
339
|
+
readonly 700: "#cc6600";
|
|
340
|
+
readonly 800: "#998c00";
|
|
341
|
+
readonly 900: "#664200";
|
|
342
|
+
readonly 950: "#332900";
|
|
343
343
|
};
|
|
344
344
|
readonly ios: {
|
|
345
345
|
readonly systemBlue: "#007AFF";
|
package/dist/lib/theme/tokens.js
CHANGED
|
@@ -335,17 +335,17 @@ exports.colors = {
|
|
|
335
335
|
950: "#052e16",
|
|
336
336
|
},
|
|
337
337
|
warning: {
|
|
338
|
-
50: "#
|
|
339
|
-
100: "#
|
|
340
|
-
200: "#
|
|
341
|
-
300: "#
|
|
342
|
-
400: "#
|
|
343
|
-
500: "#
|
|
344
|
-
600: "#
|
|
345
|
-
700: "#
|
|
346
|
-
800: "#
|
|
347
|
-
900: "#
|
|
348
|
-
950: "#
|
|
338
|
+
50: "#fffaf0",
|
|
339
|
+
100: "#ffe6c7",
|
|
340
|
+
200: "#ffd99e",
|
|
341
|
+
300: "#ffcc75",
|
|
342
|
+
400: "#ffb94e",
|
|
343
|
+
500: "#ff9e1f",
|
|
344
|
+
600: "#e67e00",
|
|
345
|
+
700: "#cc6600",
|
|
346
|
+
800: "#998c00",
|
|
347
|
+
900: "#664200",
|
|
348
|
+
950: "#332900",
|
|
349
349
|
},
|
|
350
350
|
// iOS system colors (adaptive)
|
|
351
351
|
ios: {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface DIDDocument {
|
|
2
|
+
id: string;
|
|
3
|
+
service?: Array<{
|
|
4
|
+
id: string;
|
|
5
|
+
type?: string;
|
|
6
|
+
serviceEndpoint?: string;
|
|
7
|
+
}>;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
export declare function resolveDIDDocument(did: string): Promise<DIDDocument>;
|
|
11
|
+
export declare function getPDSServiceEndpoint(didDoc: DIDDocument): string;
|
|
12
|
+
export declare function getBlob(did: string, cid: string, didDoc?: DIDDocument): Promise<Blob>;
|
|
13
|
+
//# sourceMappingURL=did.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did.d.ts","sourceRoot":"","sources":["../../src/utils/did.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;QACX,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC,CAAC;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,wBAAsB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAsB1E;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAQjE;AAED,wBAAsB,OAAO,CAC3B,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,IAAI,CAAC,CAYf"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resolveDIDDocument = resolveDIDDocument;
|
|
4
|
+
exports.getPDSServiceEndpoint = getPDSServiceEndpoint;
|
|
5
|
+
exports.getBlob = getBlob;
|
|
6
|
+
async function resolveDIDDocument(did) {
|
|
7
|
+
let didDocUrl;
|
|
8
|
+
if (did.startsWith("did:web:")) {
|
|
9
|
+
// For did:web, construct the URL directly
|
|
10
|
+
const domain = did.replace("did:web:", "").replace(/:/g, "/");
|
|
11
|
+
didDocUrl = `https://${domain}/.well-known/did.json`;
|
|
12
|
+
}
|
|
13
|
+
else if (did.startsWith("did:plc:")) {
|
|
14
|
+
// For did:plc, use plc.directory
|
|
15
|
+
didDocUrl = `https://plc.directory/${did}`;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
throw new Error(`Unsupported DID method: ${did}`);
|
|
19
|
+
}
|
|
20
|
+
const response = await fetch(didDocUrl);
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
throw new Error(`Failed to resolve DID document for ${did}: ${response.status}`);
|
|
23
|
+
}
|
|
24
|
+
return response.json();
|
|
25
|
+
}
|
|
26
|
+
function getPDSServiceEndpoint(didDoc) {
|
|
27
|
+
const pdsService = didDoc.service?.find((s) => s.id === "#atproto_pds");
|
|
28
|
+
if (!pdsService?.serviceEndpoint) {
|
|
29
|
+
throw new Error("No PDS service endpoint found in DID document");
|
|
30
|
+
}
|
|
31
|
+
return pdsService.serviceEndpoint;
|
|
32
|
+
}
|
|
33
|
+
async function getBlob(did, cid, didDoc) {
|
|
34
|
+
const doc = didDoc || (await resolveDIDDocument(did));
|
|
35
|
+
const pdsEndpoint = getPDSServiceEndpoint(doc);
|
|
36
|
+
const blobUrl = `${pdsEndpoint}/xrpc/com.atproto.sync.getBlob?did=${did}&cid=${cid}`;
|
|
37
|
+
const response = await fetch(blobUrl);
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
throw new Error(`Failed to fetch blob: ${response.status}`);
|
|
40
|
+
}
|
|
41
|
+
return response.blob();
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=did.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"did.js","sourceRoot":"","sources":["../../src/utils/did.ts"],"names":[],"mappings":";;AAUA,gDAsBC;AAED,sDAQC;AAED,0BAgBC;AAlDM,KAAK,UAAU,kBAAkB,CAAC,GAAW;IAClD,IAAI,SAAiB,CAAC;IAEtB,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,0CAA0C;QAC1C,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QAC9D,SAAS,GAAG,WAAW,MAAM,uBAAuB,CAAC;IACvD,CAAC;SAAM,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACtC,iCAAiC;QACjC,SAAS,GAAG,yBAAyB,GAAG,EAAE,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;IACxC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,sCAAsC,GAAG,KAAK,QAAQ,CAAC,MAAM,EAAE,CAChE,CAAC;IACJ,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAED,SAAgB,qBAAqB,CAAC,MAAmB;IACvD,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,cAAc,CAAC,CAAC;IAExE,IAAI,CAAC,UAAU,EAAE,eAAe,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,UAAU,CAAC,eAAe,CAAC;AACpC,CAAC;AAEM,KAAK,UAAU,OAAO,CAC3B,GAAW,EACX,GAAW,EACX,MAAoB;IAEpB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAE/C,MAAM,OAAO,GAAG,GAAG,WAAW,sCAAsC,GAAG,QAAQ,GAAG,EAAE,CAAC;IAErF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC"}
|
|
@@ -121,7 +121,7 @@ inactive = Inactive
|
|
|
121
121
|
active = Active
|
|
122
122
|
|
|
123
123
|
## Multistreaming
|
|
124
|
-
|
|
124
|
+
multistream = Multistreaming
|
|
125
125
|
multistream-targets = Multistream Targets
|
|
126
126
|
multistream-description = Automatically push your Streamplace livestreams to other streaming services like Twitch or YouTube.
|
|
127
127
|
create-multistream-target = Create Multistream Target
|
|
@@ -168,6 +168,7 @@ need-setup-live-dashboard = Need to set up streaming first? Visit the live dashb
|
|
|
168
168
|
no-languages-found = No languages found
|
|
169
169
|
|
|
170
170
|
## Branding Administration
|
|
171
|
+
branding = Branding
|
|
171
172
|
branding-admin = Branding Administration
|
|
172
173
|
branding-admin-description = Customize your Streamplace instance. Note that settings may take a few hours to propagate.
|
|
173
174
|
branding-login-required = Please log in to manage branding
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamplace/components",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.6",
|
|
4
4
|
"description": "Streamplace React (Native) Components",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "src/index.tsx",
|
|
@@ -80,5 +80,5 @@
|
|
|
80
80
|
"i18n:watch": "nodemon --watch 'locales/**/*.ftl' --exec 'node scripts/compile-translations.js'",
|
|
81
81
|
"i18n:extract": "i18next-cli extract && node scripts/migrate-i18n.js"
|
|
82
82
|
},
|
|
83
|
-
"gitHead": "
|
|
83
|
+
"gitHead": "5ea7ad20a8cbf83a0f554ba1348972cc34d9b518"
|
|
84
84
|
}
|
|
@@ -5,7 +5,6 @@ import { usePlayerStore } from "../../player-store";
|
|
|
5
5
|
import {
|
|
6
6
|
useCreateBlockRecord,
|
|
7
7
|
useCreateHideChatRecord,
|
|
8
|
-
useUpdateLivestreamRecord,
|
|
9
8
|
} from "../../streamplace-store/block";
|
|
10
9
|
import {
|
|
11
10
|
ModerationPermissions,
|
|
@@ -17,24 +16,19 @@ import { Linking } from "react-native";
|
|
|
17
16
|
import { ChatMessageViewHydrated } from "streamplace";
|
|
18
17
|
import {
|
|
19
18
|
useDeleteChatMessage,
|
|
20
|
-
useLivestream,
|
|
21
19
|
useLivestreamStore,
|
|
22
20
|
} from "../../livestream-store";
|
|
23
21
|
import { useStreamplaceStore } from "../../streamplace-store";
|
|
24
22
|
import { formatHandle, formatHandleWithAt } from "../../utils/format-handle";
|
|
25
23
|
import {
|
|
26
24
|
atoms,
|
|
27
|
-
Button,
|
|
28
|
-
DialogFooter,
|
|
29
25
|
DropdownMenu,
|
|
30
26
|
DropdownMenuGroup,
|
|
31
27
|
DropdownMenuItem,
|
|
32
28
|
DropdownMenuTrigger,
|
|
33
29
|
layout,
|
|
34
|
-
ResponsiveDialog,
|
|
35
30
|
ResponsiveDropdownMenuContent,
|
|
36
31
|
Text,
|
|
37
|
-
Textarea,
|
|
38
32
|
useToast,
|
|
39
33
|
View,
|
|
40
34
|
} from "../ui";
|
|
@@ -61,10 +55,6 @@ export const ModView = forwardRef<ModViewRef, ModViewProps>(() => {
|
|
|
61
55
|
let [messageRemoved, setMessageRemoved] = useState(false);
|
|
62
56
|
let { createBlock, isLoading: isBlockLoading } = useCreateBlockRecord();
|
|
63
57
|
let { createHideChat, isLoading: isHideLoading } = useCreateHideChatRecord();
|
|
64
|
-
let { updateLivestream, isLoading: isUpdateTitleLoading } =
|
|
65
|
-
useUpdateLivestreamRecord();
|
|
66
|
-
const livestream = useLivestream();
|
|
67
|
-
const [showUpdateTitleDialog, setShowUpdateTitleDialog] = useState(false);
|
|
68
58
|
|
|
69
59
|
const setReportModalOpen = usePlayerStore((x) => x.setReportModalOpen);
|
|
70
60
|
const setReportSubject = usePlayerStore((x) => x.setReportSubject);
|
|
@@ -95,17 +85,6 @@ export const ModView = forwardRef<ModViewRef, ModViewProps>(() => {
|
|
|
95
85
|
}
|
|
96
86
|
}, [message]);
|
|
97
87
|
|
|
98
|
-
// Early return AFTER all hooks have been called
|
|
99
|
-
if (!agent?.did) {
|
|
100
|
-
return <></>;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// Can show moderation actions if user can hide, ban, or manage livestream
|
|
104
|
-
const canModerate =
|
|
105
|
-
modPermissions.canHide ||
|
|
106
|
-
modPermissions.canBan ||
|
|
107
|
-
modPermissions.canManageLivestream;
|
|
108
|
-
|
|
109
88
|
// Check if any moderation actions are actually available for this message
|
|
110
89
|
// This must match the individual action checks inside the DropdownMenuGroup
|
|
111
90
|
const hasAvailableActions = !!(
|
|
@@ -146,9 +125,6 @@ export const ModView = forwardRef<ModViewRef, ModViewProps>(() => {
|
|
|
146
125
|
createHideChat={createHideChat}
|
|
147
126
|
createBlock={createBlock}
|
|
148
127
|
toast={toast}
|
|
149
|
-
setShowUpdateTitleDialog={setShowUpdateTitleDialog}
|
|
150
|
-
isUpdateTitleLoading={isUpdateTitleLoading}
|
|
151
|
-
livestream={livestream}
|
|
152
128
|
setReportModalOpen={setReportModalOpen}
|
|
153
129
|
setReportSubject={setReportSubject}
|
|
154
130
|
deleteChatMessage={deleteChatMessage}
|
|
@@ -156,17 +132,6 @@ export const ModView = forwardRef<ModViewRef, ModViewProps>(() => {
|
|
|
156
132
|
)}
|
|
157
133
|
</ResponsiveDropdownMenuContent>
|
|
158
134
|
</DropdownMenu>
|
|
159
|
-
|
|
160
|
-
{/* Update Stream Title Dialog - rendered outside dropdown */}
|
|
161
|
-
{showUpdateTitleDialog && (
|
|
162
|
-
<UpdateStreamTitleDialog
|
|
163
|
-
livestream={livestream}
|
|
164
|
-
streamerDID={streamerDID}
|
|
165
|
-
updateLivestream={updateLivestream}
|
|
166
|
-
isLoading={isUpdateTitleLoading}
|
|
167
|
-
onClose={() => setShowUpdateTitleDialog(false)}
|
|
168
|
-
/>
|
|
169
|
-
)}
|
|
170
135
|
</>
|
|
171
136
|
);
|
|
172
137
|
});
|
|
@@ -184,9 +149,6 @@ interface ModViewContentProps {
|
|
|
184
149
|
createHideChat: (uri: string, streamerDID?: string) => Promise<any>;
|
|
185
150
|
createBlock: (did: string, streamerDID?: string) => Promise<any>;
|
|
186
151
|
toast: ReturnType<typeof useToast>;
|
|
187
|
-
setShowUpdateTitleDialog: (show: boolean) => void;
|
|
188
|
-
isUpdateTitleLoading: boolean;
|
|
189
|
-
livestream: any;
|
|
190
152
|
setReportModalOpen: (open: boolean) => void;
|
|
191
153
|
setReportSubject: (subject: any) => void;
|
|
192
154
|
deleteChatMessage: (uri: string) => Promise<any>;
|
|
@@ -205,9 +167,6 @@ function ModViewContent({
|
|
|
205
167
|
createHideChat,
|
|
206
168
|
createBlock,
|
|
207
169
|
toast,
|
|
208
|
-
setShowUpdateTitleDialog,
|
|
209
|
-
isUpdateTitleLoading,
|
|
210
|
-
livestream,
|
|
211
170
|
setReportModalOpen,
|
|
212
171
|
setReportSubject,
|
|
213
172
|
deleteChatMessage,
|
|
@@ -301,23 +260,6 @@ function ModViewContent({
|
|
|
301
260
|
</DropdownMenuGroup>
|
|
302
261
|
)}
|
|
303
262
|
|
|
304
|
-
{modPermissions.canManageLivestream && (
|
|
305
|
-
<DropdownMenuGroup key="stream-actions" title={`Stream actions`}>
|
|
306
|
-
<DropdownMenuItem
|
|
307
|
-
onPress={() => {
|
|
308
|
-
setShowUpdateTitleDialog(true);
|
|
309
|
-
}}
|
|
310
|
-
disabled={isUpdateTitleLoading || !livestream}
|
|
311
|
-
>
|
|
312
|
-
<Text
|
|
313
|
-
color={isUpdateTitleLoading || !livestream ? "muted" : "primary"}
|
|
314
|
-
>
|
|
315
|
-
{isUpdateTitleLoading ? "Updating..." : "Update stream title"}
|
|
316
|
-
</Text>
|
|
317
|
-
</DropdownMenuItem>
|
|
318
|
-
</DropdownMenuGroup>
|
|
319
|
-
)}
|
|
320
|
-
|
|
321
263
|
<DropdownMenuGroup key="user-actions" title={`User actions`}>
|
|
322
264
|
<DropdownMenuItem
|
|
323
265
|
onPress={() => {
|
|
@@ -328,14 +270,14 @@ function ModViewContent({
|
|
|
328
270
|
>
|
|
329
271
|
<Text color="primary">View user on {BSKY_FRONTEND_DOMAIN}</Text>
|
|
330
272
|
</DropdownMenuItem>
|
|
331
|
-
{message.author.did === agent
|
|
273
|
+
{agent?.did && message.author.did === agent.did && (
|
|
332
274
|
<DeleteButton
|
|
333
275
|
message={message}
|
|
334
276
|
deleteChatMessage={deleteChatMessage}
|
|
335
277
|
onOpenChange={onOpenChange}
|
|
336
278
|
/>
|
|
337
279
|
)}
|
|
338
|
-
{message.author.did !== agent
|
|
280
|
+
{(!agent?.did || message.author.did !== agent.did) && (
|
|
339
281
|
<ReportButton
|
|
340
282
|
message={message}
|
|
341
283
|
setReportModalOpen={setReportModalOpen}
|
|
@@ -429,161 +371,3 @@ export function ReportButton({
|
|
|
429
371
|
</DropdownMenuItem>
|
|
430
372
|
);
|
|
431
373
|
}
|
|
432
|
-
|
|
433
|
-
interface UpdateStreamTitleDialogProps {
|
|
434
|
-
livestream: any;
|
|
435
|
-
streamerDID?: string;
|
|
436
|
-
updateLivestream: (
|
|
437
|
-
livestreamUri: string,
|
|
438
|
-
title: string,
|
|
439
|
-
streamerDID?: string,
|
|
440
|
-
) => Promise<any>;
|
|
441
|
-
isLoading: boolean;
|
|
442
|
-
onClose: () => void;
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
function UpdateStreamTitleDialog({
|
|
446
|
-
livestream,
|
|
447
|
-
streamerDID,
|
|
448
|
-
updateLivestream,
|
|
449
|
-
isLoading,
|
|
450
|
-
onClose,
|
|
451
|
-
}: UpdateStreamTitleDialogProps) {
|
|
452
|
-
const [title, setTitle] = useState(livestream?.record?.title || "");
|
|
453
|
-
const [error, setError] = useState<string | null>(null);
|
|
454
|
-
const toast = useToast();
|
|
455
|
-
|
|
456
|
-
useEffect(() => {
|
|
457
|
-
if (livestream?.record?.title) {
|
|
458
|
-
setTitle(livestream.record.title);
|
|
459
|
-
}
|
|
460
|
-
}, [livestream?.record?.title]);
|
|
461
|
-
|
|
462
|
-
const handleUpdate = async () => {
|
|
463
|
-
setError(null);
|
|
464
|
-
|
|
465
|
-
if (!title.trim()) {
|
|
466
|
-
setError("Please enter a stream title");
|
|
467
|
-
return;
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
if (!livestream?.uri) {
|
|
471
|
-
setError("No livestream found");
|
|
472
|
-
return;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
try {
|
|
476
|
-
await updateLivestream(livestream.uri, title.trim(), streamerDID);
|
|
477
|
-
toast.show(
|
|
478
|
-
"Stream title updated",
|
|
479
|
-
"The stream title has been successfully updated.",
|
|
480
|
-
{ duration: 3 },
|
|
481
|
-
);
|
|
482
|
-
onClose();
|
|
483
|
-
} catch (err) {
|
|
484
|
-
setError(
|
|
485
|
-
err instanceof Error ? err.message : "Failed to update stream title",
|
|
486
|
-
);
|
|
487
|
-
}
|
|
488
|
-
};
|
|
489
|
-
|
|
490
|
-
return (
|
|
491
|
-
<ResponsiveDialog
|
|
492
|
-
open={true}
|
|
493
|
-
onOpenChange={(open) => {
|
|
494
|
-
if (!open) {
|
|
495
|
-
onClose();
|
|
496
|
-
setError(null);
|
|
497
|
-
setTitle(livestream?.record?.title || "");
|
|
498
|
-
}
|
|
499
|
-
}}
|
|
500
|
-
title="Update Stream Title"
|
|
501
|
-
description="Update the title of the livestream."
|
|
502
|
-
size="md"
|
|
503
|
-
dismissible={false}
|
|
504
|
-
>
|
|
505
|
-
<View style={[{ padding: 16, paddingBottom: 0 }]}>
|
|
506
|
-
<View style={[{ marginBottom: 16 }]}>
|
|
507
|
-
<Text
|
|
508
|
-
style={[
|
|
509
|
-
{ color: atoms.colors.gray[300], fontSize: 13, marginBottom: 8 },
|
|
510
|
-
]}
|
|
511
|
-
>
|
|
512
|
-
Stream Title
|
|
513
|
-
</Text>
|
|
514
|
-
<Textarea
|
|
515
|
-
value={title}
|
|
516
|
-
onChangeText={(text) => {
|
|
517
|
-
setTitle(text);
|
|
518
|
-
setError(null);
|
|
519
|
-
}}
|
|
520
|
-
placeholder="Enter stream title..."
|
|
521
|
-
maxLength={140}
|
|
522
|
-
multiline
|
|
523
|
-
style={[
|
|
524
|
-
{
|
|
525
|
-
padding: 12,
|
|
526
|
-
borderRadius: 8,
|
|
527
|
-
backgroundColor: atoms.colors.neutral[800],
|
|
528
|
-
color: atoms.colors.white,
|
|
529
|
-
borderWidth: 1,
|
|
530
|
-
borderColor: atoms.colors.neutral[600],
|
|
531
|
-
minHeight: 100,
|
|
532
|
-
fontSize: 16,
|
|
533
|
-
},
|
|
534
|
-
]}
|
|
535
|
-
/>
|
|
536
|
-
<Text
|
|
537
|
-
style={[
|
|
538
|
-
{ color: atoms.colors.gray[400], fontSize: 12, marginTop: 4 },
|
|
539
|
-
]}
|
|
540
|
-
>
|
|
541
|
-
{title.length}/140 characters
|
|
542
|
-
</Text>
|
|
543
|
-
</View>
|
|
544
|
-
|
|
545
|
-
{error && (
|
|
546
|
-
<View
|
|
547
|
-
style={[
|
|
548
|
-
{
|
|
549
|
-
backgroundColor: atoms.colors.red[900],
|
|
550
|
-
padding: 12,
|
|
551
|
-
borderRadius: 8,
|
|
552
|
-
borderWidth: 1,
|
|
553
|
-
borderColor: atoms.colors.red[700],
|
|
554
|
-
marginBottom: 16,
|
|
555
|
-
},
|
|
556
|
-
]}
|
|
557
|
-
>
|
|
558
|
-
<Text style={[{ color: atoms.colors.red[400], fontSize: 13 }]}>
|
|
559
|
-
{error}
|
|
560
|
-
</Text>
|
|
561
|
-
</View>
|
|
562
|
-
)}
|
|
563
|
-
</View>
|
|
564
|
-
|
|
565
|
-
<DialogFooter>
|
|
566
|
-
<Button
|
|
567
|
-
width="min"
|
|
568
|
-
variant="secondary"
|
|
569
|
-
onPress={() => {
|
|
570
|
-
onClose();
|
|
571
|
-
setError(null);
|
|
572
|
-
setTitle(livestream?.record?.title || "");
|
|
573
|
-
}}
|
|
574
|
-
disabled={isLoading}
|
|
575
|
-
>
|
|
576
|
-
<Text>Cancel</Text>
|
|
577
|
-
</Button>
|
|
578
|
-
<Button
|
|
579
|
-
variant="primary"
|
|
580
|
-
width="min"
|
|
581
|
-
onPress={handleUpdate}
|
|
582
|
-
disabled={isLoading || !title.trim()}
|
|
583
|
-
>
|
|
584
|
-
<Text>{isLoading ? "Updating..." : "Update Title"}</Text>
|
|
585
|
-
</Button>
|
|
586
|
-
</DialogFooter>
|
|
587
|
-
</ResponsiveDialog>
|
|
588
|
-
);
|
|
589
|
-
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import {
|
|
3
|
+
atoms,
|
|
4
|
+
Button,
|
|
5
|
+
DialogFooter,
|
|
6
|
+
ResponsiveDialog,
|
|
7
|
+
Text,
|
|
8
|
+
Textarea,
|
|
9
|
+
useToast,
|
|
10
|
+
View,
|
|
11
|
+
} from "../ui";
|
|
12
|
+
|
|
13
|
+
export interface UpdateStreamTitleDialogProps {
|
|
14
|
+
livestream: any;
|
|
15
|
+
streamerDID?: string;
|
|
16
|
+
updateLivestream: (
|
|
17
|
+
livestreamUri: string,
|
|
18
|
+
title: string,
|
|
19
|
+
streamerDID?: string,
|
|
20
|
+
) => Promise<any>;
|
|
21
|
+
isLoading: boolean;
|
|
22
|
+
onClose: () => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function UpdateStreamTitleDialog({
|
|
26
|
+
livestream,
|
|
27
|
+
streamerDID,
|
|
28
|
+
updateLivestream,
|
|
29
|
+
isLoading,
|
|
30
|
+
onClose,
|
|
31
|
+
}: UpdateStreamTitleDialogProps) {
|
|
32
|
+
const [title, setTitle] = useState(livestream?.record?.title || "");
|
|
33
|
+
const [error, setError] = useState<string | null>(null);
|
|
34
|
+
const toast = useToast();
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
if (livestream?.record?.title) {
|
|
38
|
+
setTitle(livestream.record.title);
|
|
39
|
+
}
|
|
40
|
+
}, [livestream?.record?.title]);
|
|
41
|
+
|
|
42
|
+
const handleUpdate = async () => {
|
|
43
|
+
setError(null);
|
|
44
|
+
|
|
45
|
+
if (!title.trim()) {
|
|
46
|
+
setError("Please enter a stream title");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!livestream?.uri) {
|
|
51
|
+
setError("No livestream found");
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
try {
|
|
56
|
+
await updateLivestream(livestream.uri, title.trim(), streamerDID);
|
|
57
|
+
toast.show(
|
|
58
|
+
"Stream title updated",
|
|
59
|
+
"The stream title has been successfully updated.",
|
|
60
|
+
{ duration: 3 },
|
|
61
|
+
);
|
|
62
|
+
onClose();
|
|
63
|
+
} catch (err) {
|
|
64
|
+
setError(
|
|
65
|
+
err instanceof Error ? err.message : "Failed to update stream title",
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<ResponsiveDialog
|
|
72
|
+
open={true}
|
|
73
|
+
onOpenChange={(open) => {
|
|
74
|
+
if (!open) {
|
|
75
|
+
onClose();
|
|
76
|
+
setError(null);
|
|
77
|
+
setTitle(livestream?.record?.title || "");
|
|
78
|
+
}
|
|
79
|
+
}}
|
|
80
|
+
title="Update Stream Title"
|
|
81
|
+
description="Update the title of the livestream."
|
|
82
|
+
size="md"
|
|
83
|
+
dismissible={false}
|
|
84
|
+
>
|
|
85
|
+
<View style={[{ padding: 16, paddingBottom: 0 }]}>
|
|
86
|
+
<View style={[{ marginBottom: 16 }]}>
|
|
87
|
+
<Text
|
|
88
|
+
style={[
|
|
89
|
+
{ color: atoms.colors.gray[300], fontSize: 13, marginBottom: 8 },
|
|
90
|
+
]}
|
|
91
|
+
>
|
|
92
|
+
Stream Title
|
|
93
|
+
</Text>
|
|
94
|
+
<Textarea
|
|
95
|
+
value={title}
|
|
96
|
+
onChangeText={(text) => {
|
|
97
|
+
setTitle(text);
|
|
98
|
+
setError(null);
|
|
99
|
+
}}
|
|
100
|
+
placeholder="Enter stream title..."
|
|
101
|
+
maxLength={140}
|
|
102
|
+
multiline
|
|
103
|
+
style={[
|
|
104
|
+
{
|
|
105
|
+
padding: 12,
|
|
106
|
+
borderRadius: 8,
|
|
107
|
+
backgroundColor: atoms.colors.neutral[800],
|
|
108
|
+
color: atoms.colors.white,
|
|
109
|
+
borderWidth: 1,
|
|
110
|
+
borderColor: atoms.colors.neutral[600],
|
|
111
|
+
minHeight: 100,
|
|
112
|
+
fontSize: 16,
|
|
113
|
+
},
|
|
114
|
+
]}
|
|
115
|
+
/>
|
|
116
|
+
<Text
|
|
117
|
+
style={[
|
|
118
|
+
{ color: atoms.colors.gray[400], fontSize: 12, marginTop: 4 },
|
|
119
|
+
]}
|
|
120
|
+
>
|
|
121
|
+
{title.length}/140 characters
|
|
122
|
+
</Text>
|
|
123
|
+
</View>
|
|
124
|
+
|
|
125
|
+
{error && (
|
|
126
|
+
<View
|
|
127
|
+
style={[
|
|
128
|
+
{
|
|
129
|
+
backgroundColor: atoms.colors.red[900],
|
|
130
|
+
padding: 12,
|
|
131
|
+
borderRadius: 8,
|
|
132
|
+
borderWidth: 1,
|
|
133
|
+
borderColor: atoms.colors.red[700],
|
|
134
|
+
marginBottom: 16,
|
|
135
|
+
},
|
|
136
|
+
]}
|
|
137
|
+
>
|
|
138
|
+
<Text style={[{ color: atoms.colors.red[400], fontSize: 13 }]}>
|
|
139
|
+
{error}
|
|
140
|
+
</Text>
|
|
141
|
+
</View>
|
|
142
|
+
)}
|
|
143
|
+
</View>
|
|
144
|
+
|
|
145
|
+
<DialogFooter>
|
|
146
|
+
<Button
|
|
147
|
+
width="min"
|
|
148
|
+
variant="secondary"
|
|
149
|
+
onPress={() => {
|
|
150
|
+
onClose();
|
|
151
|
+
setError(null);
|
|
152
|
+
setTitle(livestream?.record?.title || "");
|
|
153
|
+
}}
|
|
154
|
+
disabled={isLoading}
|
|
155
|
+
>
|
|
156
|
+
<Text>Cancel</Text>
|
|
157
|
+
</Button>
|
|
158
|
+
<Button
|
|
159
|
+
variant="primary"
|
|
160
|
+
width="min"
|
|
161
|
+
onPress={handleUpdate}
|
|
162
|
+
disabled={isLoading || !title.trim()}
|
|
163
|
+
>
|
|
164
|
+
<Text>{isLoading ? "Updating..." : "Update Title"}</Text>
|
|
165
|
+
</Button>
|
|
166
|
+
</DialogFooter>
|
|
167
|
+
</ResponsiveDialog>
|
|
168
|
+
);
|
|
169
|
+
}
|