@streamplace/components 0.7.35 → 0.8.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.
- package/dist/components/content-metadata/content-metadata-form.js +467 -0
- package/dist/components/content-metadata/content-rights.js +78 -0
- package/dist/components/content-metadata/content-warnings.js +68 -0
- package/dist/components/content-metadata/index.js +11 -0
- package/dist/components/mobile-player/player.js +4 -0
- package/dist/components/mobile-player/ui/report-modal.js +3 -2
- package/dist/components/ui/checkbox.js +87 -0
- package/dist/components/ui/dialog.js +188 -83
- package/dist/components/ui/primitives/input.js +13 -1
- package/dist/components/ui/primitives/modal.js +2 -2
- package/dist/components/ui/select.js +89 -0
- package/dist/components/ui/textarea.js +23 -4
- package/dist/components/ui/toast.js +464 -114
- package/dist/components/ui/tooltip.js +103 -0
- package/dist/index.js +2 -0
- package/dist/lib/metadata-constants.js +157 -0
- package/dist/lib/theme/theme.js +5 -3
- package/dist/streamplace-provider/index.js +14 -4
- package/dist/streamplace-store/content-metadata-actions.js +124 -0
- package/dist/streamplace-store/streamplace-store.js +22 -5
- package/dist/streamplace-store/user.js +67 -7
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/package.json +3 -3
- package/src/components/content-metadata/content-metadata-form.tsx +893 -0
- package/src/components/content-metadata/content-rights.tsx +104 -0
- package/src/components/content-metadata/content-warnings.tsx +100 -0
- package/src/components/content-metadata/index.tsx +10 -0
- package/src/components/mobile-player/player.tsx +5 -0
- package/src/components/mobile-player/ui/report-modal.tsx +13 -7
- package/src/components/ui/checkbox.tsx +147 -0
- package/src/components/ui/dialog.tsx +319 -99
- package/src/components/ui/primitives/input.tsx +19 -2
- package/src/components/ui/primitives/modal.tsx +4 -2
- package/src/components/ui/select.tsx +175 -0
- package/src/components/ui/textarea.tsx +47 -29
- package/src/components/ui/toast.tsx +785 -179
- package/src/components/ui/tooltip.tsx +131 -0
- package/src/index.tsx +3 -0
- package/src/lib/metadata-constants.ts +180 -0
- package/src/lib/theme/theme.tsx +10 -6
- package/src/streamplace-provider/index.tsx +20 -2
- package/src/streamplace-store/content-metadata-actions.tsx +145 -0
- package/src/streamplace-store/streamplace-store.tsx +41 -4
- package/src/streamplace-store/user.tsx +71 -7
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentMetadataForm = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
6
|
+
const react_1 = require("react");
|
|
7
|
+
const react_native_1 = require("react-native");
|
|
8
|
+
const metadata_constants_1 = require("../../lib/metadata-constants");
|
|
9
|
+
const content_metadata_actions_1 = require("../../streamplace-store/content-metadata-actions");
|
|
10
|
+
const streamplace_store_1 = require("../../streamplace-store/streamplace-store");
|
|
11
|
+
const xrpc_1 = require("../../streamplace-store/xrpc");
|
|
12
|
+
const zero = tslib_1.__importStar(require("../../ui"));
|
|
13
|
+
const button_1 = require("../ui/button");
|
|
14
|
+
const checkbox_1 = require("../ui/checkbox");
|
|
15
|
+
const input_1 = require("../ui/input");
|
|
16
|
+
const select_1 = require("../ui/select");
|
|
17
|
+
const text_1 = require("../ui/text");
|
|
18
|
+
const textarea_1 = require("../ui/textarea");
|
|
19
|
+
const toast_1 = require("../ui/toast");
|
|
20
|
+
const tooltip_1 = require("../ui/tooltip");
|
|
21
|
+
const { p, r, bg, borders, w, text, layout, gap, flex } = zero;
|
|
22
|
+
// ButtonSelector component (same as in livestream-panel)
|
|
23
|
+
const ButtonSelector = ({ values, selectedValue, setSelectedValue, disabledValues = [], style = [], }) => ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [layout.flex.row, gap.all[1], ...style], children: values.map(({ label, value }) => ((0, jsx_runtime_1.jsx)(button_1.Button, { variant: selectedValue === value ? "primary" : "secondary", size: "pill", disabled: disabledValues.includes(value), onPress: () => setSelectedValue(value), style: [
|
|
24
|
+
r.md,
|
|
25
|
+
{
|
|
26
|
+
opacity: disabledValues.includes(value) ? 0.5 : 1,
|
|
27
|
+
},
|
|
28
|
+
], children: (0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
29
|
+
selectedValue === value ? text.white : text.gray[300],
|
|
30
|
+
{ fontSize: 14, fontWeight: "600" },
|
|
31
|
+
], children: label }) }, value))) }));
|
|
32
|
+
exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = false, onMetadataChange, initialMetadata, style }, ref) => {
|
|
33
|
+
const pdsAgent = (0, xrpc_1.usePDSAgent)();
|
|
34
|
+
const did = (0, streamplace_store_1.useDID)();
|
|
35
|
+
const getContentMetadata = (0, content_metadata_actions_1.useGetContentMetadata)();
|
|
36
|
+
const saveContentMetadata = (0, content_metadata_actions_1.useSaveContentMetadata)();
|
|
37
|
+
const toast = (0, toast_1.useToast)();
|
|
38
|
+
// Local state for metadata
|
|
39
|
+
const [contentWarnings, setContentWarnings] = (0, react_1.useState)([]);
|
|
40
|
+
const [distributionPolicy, setDistributionPolicy] = (0, react_1.useState)({});
|
|
41
|
+
const [contentRights, setContentRights] = (0, react_1.useState)({});
|
|
42
|
+
const [selectedLicense, setSelectedLicense] = (0, react_1.useState)("");
|
|
43
|
+
const [customLicenseText, setCustomLicenseText] = (0, react_1.useState)("");
|
|
44
|
+
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
45
|
+
const [hasMetadata, setHasMetadata] = (0, react_1.useState)(false);
|
|
46
|
+
// State for section toggles
|
|
47
|
+
const [activeSection, setActiveSection] = (0, react_1.useState)("contentWarnings");
|
|
48
|
+
const currentYear = new Date().getFullYear();
|
|
49
|
+
const getBroadcasterDID = (0, content_metadata_actions_1.useGetBroadcasterDID)();
|
|
50
|
+
(0, react_1.useEffect)(() => {
|
|
51
|
+
getBroadcasterDID();
|
|
52
|
+
}, [getBroadcasterDID]);
|
|
53
|
+
const broadcasterDID = (0, streamplace_store_1.useStreamplaceStore)((state) => state.broadcasterDID);
|
|
54
|
+
// Load existing metadata on mount or from initialMetadata prop
|
|
55
|
+
(0, react_1.useEffect)(() => {
|
|
56
|
+
if (initialMetadata) {
|
|
57
|
+
// Use provided initial metadata
|
|
58
|
+
if (initialMetadata.contentWarnings?.warnings) {
|
|
59
|
+
setContentWarnings(initialMetadata.contentWarnings.warnings);
|
|
60
|
+
}
|
|
61
|
+
if (initialMetadata.distributionPolicy) {
|
|
62
|
+
setDistributionPolicy(initialMetadata.distributionPolicy);
|
|
63
|
+
}
|
|
64
|
+
if (initialMetadata.contentRights) {
|
|
65
|
+
setContentRights(initialMetadata.contentRights);
|
|
66
|
+
setSelectedLicense(initialMetadata.contentRights.license || "");
|
|
67
|
+
}
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
const loadMetadata = async () => {
|
|
71
|
+
if (!pdsAgent || !did)
|
|
72
|
+
return;
|
|
73
|
+
try {
|
|
74
|
+
const metadata = await getContentMetadata();
|
|
75
|
+
if (metadata?.record) {
|
|
76
|
+
setHasMetadata(true);
|
|
77
|
+
if (metadata.record.contentWarnings?.warnings) {
|
|
78
|
+
setContentWarnings(metadata.record.contentWarnings.warnings);
|
|
79
|
+
}
|
|
80
|
+
if (metadata.record.distributionPolicy) {
|
|
81
|
+
setDistributionPolicy(metadata.record.distributionPolicy);
|
|
82
|
+
}
|
|
83
|
+
if (metadata.record.contentRights) {
|
|
84
|
+
setContentRights(metadata.record.contentRights);
|
|
85
|
+
setSelectedLicense(metadata.record.contentRights.license || "");
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
// No existing metadata is fine
|
|
91
|
+
console.log("No existing metadata found");
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
loadMetadata();
|
|
95
|
+
}, [pdsAgent, did, initialMetadata]);
|
|
96
|
+
const handleContentWarningChange = (0, react_1.useCallback)((warning, checked) => {
|
|
97
|
+
const newWarnings = checked
|
|
98
|
+
? [...contentWarnings, warning]
|
|
99
|
+
: contentWarnings.filter((w) => w !== warning);
|
|
100
|
+
setContentWarnings(newWarnings);
|
|
101
|
+
if (onMetadataChange) {
|
|
102
|
+
onMetadataChange({
|
|
103
|
+
$type: "place.stream.metadata.configuration",
|
|
104
|
+
contentWarnings: { warnings: newWarnings },
|
|
105
|
+
distributionPolicy,
|
|
106
|
+
contentRights,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
}, [contentWarnings, distributionPolicy, contentRights, onMetadataChange]);
|
|
110
|
+
// Notify parent component when metadata changes
|
|
111
|
+
(0, react_1.useEffect)(() => {
|
|
112
|
+
if (onMetadataChange) {
|
|
113
|
+
onMetadataChange({
|
|
114
|
+
$type: "place.stream.metadata.configuration",
|
|
115
|
+
contentWarnings: { warnings: contentWarnings },
|
|
116
|
+
distributionPolicy,
|
|
117
|
+
contentRights,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}, [contentWarnings, distributionPolicy, contentRights, onMetadataChange]);
|
|
121
|
+
// Handle distribution policy changes
|
|
122
|
+
const handleDistributionPolicyChange = (0, react_1.useCallback)(({ deleteAfter, allowedBroadcasters, }) => {
|
|
123
|
+
let newDistributionPolicy = {
|
|
124
|
+
...distributionPolicy,
|
|
125
|
+
};
|
|
126
|
+
if (typeof deleteAfter === "string") {
|
|
127
|
+
let duration = parseInt(deleteAfter, 10);
|
|
128
|
+
if (isNaN(duration)) {
|
|
129
|
+
newDistributionPolicy.deleteAfter = undefined;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
if (isNaN(duration) || duration < 0) {
|
|
133
|
+
duration = -1;
|
|
134
|
+
}
|
|
135
|
+
newDistributionPolicy.deleteAfter =
|
|
136
|
+
duration === 0 ? undefined : duration;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (typeof allowedBroadcasters === "string") {
|
|
140
|
+
newDistributionPolicy.allowedBroadcasters =
|
|
141
|
+
allowedBroadcasters.split("\n");
|
|
142
|
+
}
|
|
143
|
+
setDistributionPolicy(newDistributionPolicy);
|
|
144
|
+
if (onMetadataChange) {
|
|
145
|
+
onMetadataChange({
|
|
146
|
+
$type: "place.stream.metadata.configuration",
|
|
147
|
+
contentWarnings: { warnings: contentWarnings },
|
|
148
|
+
distributionPolicy: newDistributionPolicy,
|
|
149
|
+
contentRights,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}, [
|
|
153
|
+
contentWarnings,
|
|
154
|
+
contentRights,
|
|
155
|
+
onMetadataChange,
|
|
156
|
+
distributionPolicy,
|
|
157
|
+
setDistributionPolicy,
|
|
158
|
+
]);
|
|
159
|
+
// Handle content rights changes
|
|
160
|
+
const handleContentRightsChange = (0, react_1.useCallback)((field, value) => {
|
|
161
|
+
const newRights = { ...contentRights, [field]: value };
|
|
162
|
+
setContentRights(newRights);
|
|
163
|
+
if (onMetadataChange) {
|
|
164
|
+
onMetadataChange({
|
|
165
|
+
$type: "place.stream.metadata.configuration",
|
|
166
|
+
contentWarnings: { warnings: contentWarnings },
|
|
167
|
+
distributionPolicy,
|
|
168
|
+
contentRights: newRights,
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
}, [contentWarnings, distributionPolicy, contentRights, onMetadataChange]);
|
|
172
|
+
const handleSave = (0, react_1.useCallback)(async () => {
|
|
173
|
+
setLoading(true);
|
|
174
|
+
try {
|
|
175
|
+
// Build the metadata object, only including non-empty fields
|
|
176
|
+
const metadata = {
|
|
177
|
+
$type: "place.stream.metadata.configuration",
|
|
178
|
+
};
|
|
179
|
+
// Only include contentWarnings if it has values
|
|
180
|
+
if (contentWarnings && contentWarnings.length > 0) {
|
|
181
|
+
metadata.contentWarnings = { warnings: contentWarnings };
|
|
182
|
+
}
|
|
183
|
+
// Only include contentRights if it has actual values
|
|
184
|
+
const rightsWithLicense = {
|
|
185
|
+
...contentRights,
|
|
186
|
+
license: selectedLicense === "custom"
|
|
187
|
+
? customLicenseText
|
|
188
|
+
: selectedLicense || undefined,
|
|
189
|
+
};
|
|
190
|
+
// Filter out empty values from contentRights and convert copyrightYear to number
|
|
191
|
+
const filteredRights = Object.fromEntries(Object.entries(rightsWithLicense)
|
|
192
|
+
.filter(([_, value]) => value !== undefined && value !== null && value !== "")
|
|
193
|
+
.map(([key, value]) => {
|
|
194
|
+
// Convert copyrightYear to integer as per lexicon
|
|
195
|
+
if (key === "copyrightYear" && typeof value === "string") {
|
|
196
|
+
const year = parseInt(value, 10);
|
|
197
|
+
return [key, isNaN(year) ? undefined : year];
|
|
198
|
+
}
|
|
199
|
+
return [key, value];
|
|
200
|
+
})
|
|
201
|
+
.filter(([_, value]) => value !== undefined));
|
|
202
|
+
if (Object.keys(filteredRights).length > 0) {
|
|
203
|
+
metadata.contentRights = filteredRights;
|
|
204
|
+
}
|
|
205
|
+
metadata.distributionPolicy = {
|
|
206
|
+
...distributionPolicy,
|
|
207
|
+
};
|
|
208
|
+
if (distributionPolicy?.allowedBroadcasters) {
|
|
209
|
+
const filteredBs = distributionPolicy.allowedBroadcasters.filter((broadcaster) => broadcaster !== "");
|
|
210
|
+
metadata.distributionPolicy.allowedBroadcasters = filteredBs;
|
|
211
|
+
setDistributionPolicy({
|
|
212
|
+
...distributionPolicy,
|
|
213
|
+
allowedBroadcasters: filteredBs,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
await saveContentMetadata(metadata);
|
|
217
|
+
setHasMetadata(true);
|
|
218
|
+
// Show success toast
|
|
219
|
+
toast.show(hasMetadata ? "Content metadata updated" : "Content metadata created", "Your settings have been saved successfully");
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
console.error("Failed to save metadata:", error);
|
|
223
|
+
// Show error toast
|
|
224
|
+
toast.show("Failed to save metadata", "Please try again later");
|
|
225
|
+
}
|
|
226
|
+
finally {
|
|
227
|
+
setLoading(false);
|
|
228
|
+
}
|
|
229
|
+
}, [
|
|
230
|
+
contentWarnings,
|
|
231
|
+
contentRights,
|
|
232
|
+
selectedLicense,
|
|
233
|
+
customLicenseText,
|
|
234
|
+
hasMetadata,
|
|
235
|
+
saveContentMetadata,
|
|
236
|
+
]);
|
|
237
|
+
return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (0, jsx_runtime_1.jsx)(react_native_1.ScrollView, { ref: ref, style: [{ flex: 1 }, style], showsVerticalScrollIndicator: false, contentContainerStyle: { flexGrow: 1 }, children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [gap.all[8], w.percent[100], { alignItems: "stretch" }], children: [(0, jsx_runtime_1.jsx)(react_native_1.View, { style: [gap.all[4], w.percent[100]], children: (0, jsx_runtime_1.jsx)(ButtonSelector, { values: [
|
|
238
|
+
{ label: "Content Warnings", value: "contentWarnings" },
|
|
239
|
+
{ label: "Content Rights", value: "contentRights" },
|
|
240
|
+
{ label: "Distribution", value: "distribution" },
|
|
241
|
+
], selectedValue: activeSection, setSelectedValue: setActiveSection, style: [{ marginVertical: -2, flexDirection: "column" }] }) }), activeSection === "contentWarnings" && ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [gap.all[3], w.percent[100]], children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
242
|
+
layout.flex.row,
|
|
243
|
+
layout.flex.alignCenter,
|
|
244
|
+
w.percent[100],
|
|
245
|
+
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
246
|
+
text.neutral[300],
|
|
247
|
+
{
|
|
248
|
+
minWidth: 100,
|
|
249
|
+
textAlign: "left",
|
|
250
|
+
paddingBottom: 8,
|
|
251
|
+
fontSize: 14,
|
|
252
|
+
},
|
|
253
|
+
], children: "Content Warnings" }), (0, jsx_runtime_1.jsx)(text_1.Text, { style: [text.gray[500], { fontSize: 12, paddingBottom: 8 }], children: "optional" })] }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [gap.all[2], w.percent[100]], children: metadata_constants_1.CONTENT_WARNINGS.map((warning) => ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [w.percent[100]], children: (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { content: warning.description, position: "top", children: (0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { checked: contentWarnings.includes(warning.value), onCheckedChange: (checked) => handleContentWarningChange(warning.value, checked), label: warning.label, style: [{ fontSize: 12 }] }) }) }, warning.value))) })] })), activeSection === "contentRights" && ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [gap.all[3], w.percent[100]], children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
254
|
+
layout.flex.row,
|
|
255
|
+
layout.flex.alignCenter,
|
|
256
|
+
w.percent[100],
|
|
257
|
+
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
258
|
+
text.neutral[300],
|
|
259
|
+
{
|
|
260
|
+
minWidth: 100,
|
|
261
|
+
textAlign: "left",
|
|
262
|
+
paddingBottom: 8,
|
|
263
|
+
fontSize: 14,
|
|
264
|
+
},
|
|
265
|
+
], children: "Content Rights" }), (0, jsx_runtime_1.jsx)(text_1.Text, { style: [text.gray[500], { fontSize: 12, paddingBottom: 8 }], children: "optional" })] }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [gap.all[3], w.percent[100]], children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
266
|
+
layout.flex.row,
|
|
267
|
+
layout.flex.alignCenter,
|
|
268
|
+
w.percent[100],
|
|
269
|
+
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
270
|
+
text.neutral[300],
|
|
271
|
+
{
|
|
272
|
+
minWidth: 100,
|
|
273
|
+
textAlign: "left",
|
|
274
|
+
paddingBottom: 8,
|
|
275
|
+
fontSize: 14,
|
|
276
|
+
},
|
|
277
|
+
], children: "Copyright Year" }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [flex.values[1]], children: (0, jsx_runtime_1.jsx)(input_1.Input, { value: contentRights.copyrightYear?.toString() || "", onChange: (value) => handleContentRightsChange("copyrightYear", value), placeholder: currentYear.toString(), variant: "filled", inputStyle: [
|
|
278
|
+
p[3],
|
|
279
|
+
r.md,
|
|
280
|
+
bg.neutral[800],
|
|
281
|
+
text.white,
|
|
282
|
+
borders.width.thin,
|
|
283
|
+
borders.color.neutral[600],
|
|
284
|
+
w.percent[100],
|
|
285
|
+
] }) })] }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
286
|
+
layout.flex.row,
|
|
287
|
+
layout.flex.alignCenter,
|
|
288
|
+
w.percent[100],
|
|
289
|
+
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
290
|
+
text.neutral[300],
|
|
291
|
+
{
|
|
292
|
+
minWidth: 100,
|
|
293
|
+
textAlign: "left",
|
|
294
|
+
paddingBottom: 8,
|
|
295
|
+
fontSize: 14,
|
|
296
|
+
},
|
|
297
|
+
], children: "License" }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [flex.values[1]], children: (0, jsx_runtime_1.jsx)(select_1.Select, { value: selectedLicense, onValueChange: (value) => {
|
|
298
|
+
setSelectedLicense(value);
|
|
299
|
+
handleContentRightsChange("license", value === "custom" ? customLicenseText : value);
|
|
300
|
+
}, placeholder: "Select a license", items: metadata_constants_1.LICENSE_OPTIONS.map((opt) => ({
|
|
301
|
+
label: opt.label,
|
|
302
|
+
value: opt.value,
|
|
303
|
+
description: opt.description,
|
|
304
|
+
})), style: [
|
|
305
|
+
p[3],
|
|
306
|
+
r.md,
|
|
307
|
+
bg.neutral[800],
|
|
308
|
+
text.white,
|
|
309
|
+
borders.width.thin,
|
|
310
|
+
borders.color.neutral[600],
|
|
311
|
+
w.percent[100],
|
|
312
|
+
] }) })] }), selectedLicense === "custom" && ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
313
|
+
layout.flex.row,
|
|
314
|
+
layout.flex.alignCenter,
|
|
315
|
+
w.percent[100],
|
|
316
|
+
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
317
|
+
text.neutral[300],
|
|
318
|
+
{
|
|
319
|
+
minWidth: 100,
|
|
320
|
+
textAlign: "left",
|
|
321
|
+
paddingBottom: 8,
|
|
322
|
+
fontSize: 14,
|
|
323
|
+
},
|
|
324
|
+
], children: "Custom License" }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [flex.values[1]], children: (0, jsx_runtime_1.jsx)(textarea_1.Textarea, { value: customLicenseText, onChangeText: (value) => {
|
|
325
|
+
setCustomLicenseText(value);
|
|
326
|
+
if (selectedLicense === "custom") {
|
|
327
|
+
handleContentRightsChange("license", value);
|
|
328
|
+
}
|
|
329
|
+
}, placeholder: "Enter your custom license terms...", style: [
|
|
330
|
+
p[3],
|
|
331
|
+
r.md,
|
|
332
|
+
bg.neutral[800],
|
|
333
|
+
text.white,
|
|
334
|
+
borders.width.thin,
|
|
335
|
+
borders.color.neutral[600],
|
|
336
|
+
w.percent[100],
|
|
337
|
+
] }) })] })), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
338
|
+
layout.flex.row,
|
|
339
|
+
layout.flex.alignCenter,
|
|
340
|
+
w.percent[100],
|
|
341
|
+
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
342
|
+
text.neutral[300],
|
|
343
|
+
{
|
|
344
|
+
minWidth: 100,
|
|
345
|
+
textAlign: "left",
|
|
346
|
+
paddingBottom: 8,
|
|
347
|
+
fontSize: 14,
|
|
348
|
+
},
|
|
349
|
+
], children: "Copyright Notice" }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [flex.values[1]], children: (0, jsx_runtime_1.jsx)(textarea_1.Textarea, { value: contentRights.copyrightNotice || "", onChangeText: (value) => handleContentRightsChange("copyrightNotice", value), placeholder: "Enter your copyright notice...", style: [
|
|
350
|
+
p[3],
|
|
351
|
+
r.md,
|
|
352
|
+
bg.neutral[800],
|
|
353
|
+
text.white,
|
|
354
|
+
borders.width.thin,
|
|
355
|
+
borders.color.neutral[600],
|
|
356
|
+
w.percent[100],
|
|
357
|
+
] }) })] }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
358
|
+
layout.flex.row,
|
|
359
|
+
layout.flex.alignCenter,
|
|
360
|
+
w.percent[100],
|
|
361
|
+
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
362
|
+
text.neutral[300],
|
|
363
|
+
{
|
|
364
|
+
minWidth: 100,
|
|
365
|
+
textAlign: "left",
|
|
366
|
+
paddingBottom: 8,
|
|
367
|
+
fontSize: 14,
|
|
368
|
+
},
|
|
369
|
+
], children: "Credit Line" }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [flex.values[1]], children: (0, jsx_runtime_1.jsx)(textarea_1.Textarea, { value: contentRights.creditLine || "", onChangeText: (value) => handleContentRightsChange("creditLine", value), placeholder: "Enter your credit line...", style: [
|
|
370
|
+
p[3],
|
|
371
|
+
r.md,
|
|
372
|
+
bg.neutral[800],
|
|
373
|
+
text.white,
|
|
374
|
+
borders.width.thin,
|
|
375
|
+
borders.color.neutral[600],
|
|
376
|
+
w.percent[100],
|
|
377
|
+
] }) })] })] })] })), activeSection === "distribution" && ((0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [gap.all[3], w.percent[100]], children: [(0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
378
|
+
layout.flex.row,
|
|
379
|
+
layout.flex.alignCenter,
|
|
380
|
+
w.percent[100],
|
|
381
|
+
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
382
|
+
text.neutral[300],
|
|
383
|
+
{ minWidth: 100, textAlign: "left", paddingBottom: 8 },
|
|
384
|
+
], children: "Distribution" }), (0, jsx_runtime_1.jsx)(text_1.Text, { style: [text.gray[500], { fontSize: 12, paddingBottom: 8 }], children: "optional" })] }), (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { content: "Distribution of your content is unlimited, but they still have to respect the deleteAfter policy below.", position: "top", children: (0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { checked: distributionPolicy.allowedBroadcasters?.includes("*") ||
|
|
385
|
+
false, onCheckedChange: (checked) => handleDistributionPolicyChange({
|
|
386
|
+
allowedBroadcasters: checked
|
|
387
|
+
? "*"
|
|
388
|
+
: broadcasterDID || "",
|
|
389
|
+
}), label: "Allow everyone to distribute your content", style: [{ fontSize: 12 }] }) }), !distributionPolicy.allowedBroadcasters?.includes("*") && ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [gap.all[3], w.percent[100]], children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
390
|
+
layout.flex.row,
|
|
391
|
+
layout.flex.alignCenter,
|
|
392
|
+
w.percent[100],
|
|
393
|
+
], children: [(0, jsx_runtime_1.jsxs)(text_1.Text, { style: [
|
|
394
|
+
text.neutral[300],
|
|
395
|
+
{
|
|
396
|
+
minWidth: 100,
|
|
397
|
+
textAlign: "left",
|
|
398
|
+
paddingBottom: 8,
|
|
399
|
+
fontSize: 14,
|
|
400
|
+
},
|
|
401
|
+
], children: ["Allowed", (0, jsx_runtime_1.jsx)("br", {}), "Broadcasters"] }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [flex.values[1]], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
402
|
+
text.gray[500],
|
|
403
|
+
{ fontSize: 12, paddingBottom: 4 },
|
|
404
|
+
], children: "Enter the did:webs of the broadcasters you want to allow to distribute your content, one per line." }), (0, jsx_runtime_1.jsx)(input_1.Input, { multiline: true, numberOfLines: 4, value: distributionPolicy.allowedBroadcasters?.join("\n") || "", onChange: (value) => {
|
|
405
|
+
handleDistributionPolicyChange({
|
|
406
|
+
allowedBroadcasters: value,
|
|
407
|
+
});
|
|
408
|
+
}, variant: "filled", inputStyle: [
|
|
409
|
+
p[3],
|
|
410
|
+
r.md,
|
|
411
|
+
bg.neutral[800],
|
|
412
|
+
text.white,
|
|
413
|
+
borders.width.thin,
|
|
414
|
+
borders.color.neutral[600],
|
|
415
|
+
w.percent[100],
|
|
416
|
+
] })] })] }) })), (0, jsx_runtime_1.jsx)(tooltip_1.Tooltip, { content: "Anyone may archive your content indefinitely.", position: "top", children: (0, jsx_runtime_1.jsx)(checkbox_1.Checkbox, { checked: distributionPolicy.deleteAfter === -1, onCheckedChange: (checked) => {
|
|
417
|
+
if (checked) {
|
|
418
|
+
handleDistributionPolicyChange({
|
|
419
|
+
deleteAfter: "-1",
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
else {
|
|
423
|
+
handleDistributionPolicyChange({
|
|
424
|
+
deleteAfter: "300",
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
}, label: "Allow everyone to archive your content", style: [{ fontSize: 12 }] }) }), distributionPolicy.deleteAfter !== -1 && ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: [gap.all[3], w.percent[100]], children: (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [
|
|
428
|
+
layout.flex.row,
|
|
429
|
+
layout.flex.alignCenter,
|
|
430
|
+
w.percent[100],
|
|
431
|
+
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
432
|
+
text.neutral[300],
|
|
433
|
+
{
|
|
434
|
+
minWidth: 100,
|
|
435
|
+
textAlign: "left",
|
|
436
|
+
paddingBottom: 8,
|
|
437
|
+
fontSize: 14,
|
|
438
|
+
},
|
|
439
|
+
], children: "Delete After" }), (0, jsx_runtime_1.jsxs)(react_native_1.View, { style: [flex.values[1]], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
440
|
+
text.gray[500],
|
|
441
|
+
{ fontSize: 12, paddingBottom: 4 },
|
|
442
|
+
], children: "Duration in seconds (e.g., 300 for 5 minutes)" }), (0, jsx_runtime_1.jsx)(input_1.Input, { value: distributionPolicy.deleteAfter?.toString() || "", onChange: (value) => {
|
|
443
|
+
handleDistributionPolicyChange({
|
|
444
|
+
deleteAfter: value,
|
|
445
|
+
});
|
|
446
|
+
}, keyboardType: "numeric", variant: "filled", inputStyle: [
|
|
447
|
+
p[3],
|
|
448
|
+
r.md,
|
|
449
|
+
bg.neutral[800],
|
|
450
|
+
text.white,
|
|
451
|
+
borders.width.thin,
|
|
452
|
+
borders.color.neutral[600],
|
|
453
|
+
w.percent[100],
|
|
454
|
+
] })] })] }) }))] })), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: [layout.flex.center, w.percent[100]], children: (0, jsx_runtime_1.jsx)(button_1.Button, { onPress: handleSave, loading: loading, disabled: loading, style: [
|
|
455
|
+
bg.primary[500],
|
|
456
|
+
r.md,
|
|
457
|
+
gap.all[3],
|
|
458
|
+
{ minWidth: 200 },
|
|
459
|
+
layout.flex.center,
|
|
460
|
+
{ opacity: loading ? 0.5 : 1 },
|
|
461
|
+
], children: (0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
462
|
+
text.white,
|
|
463
|
+
w.percent[100],
|
|
464
|
+
{ fontSize: 16, fontWeight: "bold" },
|
|
465
|
+
], children: hasMetadata ? "Update Metadata" : "Save Metadata" }) }) })] }) }) }));
|
|
466
|
+
});
|
|
467
|
+
exports.ContentMetadataForm.displayName = "ContentMetadataForm";
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentRights = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const react_native_1 = require("react-native");
|
|
7
|
+
const metadata_constants_1 = require("../../lib/metadata-constants");
|
|
8
|
+
const theme_1 = require("../../lib/theme/theme");
|
|
9
|
+
const text_1 = require("../ui/text");
|
|
10
|
+
exports.ContentRights = (0, react_1.forwardRef)(({ contentRights }, ref) => {
|
|
11
|
+
const { theme } = (0, theme_1.useTheme)();
|
|
12
|
+
if (!contentRights || Object.keys(contentRights).length === 0) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const styles = createStyles(theme);
|
|
16
|
+
const formatLicense = (license) => {
|
|
17
|
+
return metadata_constants_1.LICENSE_URL_LABELS[license] || license;
|
|
18
|
+
};
|
|
19
|
+
// Display rights in bottom metadata view
|
|
20
|
+
const elements = [];
|
|
21
|
+
// TODO: Map DID to handle creator
|
|
22
|
+
// if (contentRights.creator) {
|
|
23
|
+
// elements.push(`Creator: ${contentRights.creator}`);
|
|
24
|
+
// }
|
|
25
|
+
if (contentRights.copyrightYear) {
|
|
26
|
+
elements.push(`© ${contentRights.copyrightYear.toString()}`);
|
|
27
|
+
}
|
|
28
|
+
if (contentRights.license) {
|
|
29
|
+
elements.push(formatLicense(contentRights.license));
|
|
30
|
+
}
|
|
31
|
+
if (contentRights.copyrightNotice) {
|
|
32
|
+
elements.push(contentRights.copyrightNotice);
|
|
33
|
+
}
|
|
34
|
+
if (contentRights.creditLine) {
|
|
35
|
+
elements.push(contentRights.creditLine);
|
|
36
|
+
}
|
|
37
|
+
return ((0, jsx_runtime_1.jsx)(react_native_1.View, { ref: ref, style: styles.compactContainer, children: (0, jsx_runtime_1.jsx)(text_1.Text, { style: styles.compactText, children: elements.join(" • ") }) }));
|
|
38
|
+
});
|
|
39
|
+
exports.ContentRights.displayName = "ContentRights";
|
|
40
|
+
function createStyles(theme) {
|
|
41
|
+
return react_native_1.StyleSheet.create({
|
|
42
|
+
container: {
|
|
43
|
+
paddingVertical: theme.spacing[3],
|
|
44
|
+
},
|
|
45
|
+
title: {
|
|
46
|
+
fontSize: 14,
|
|
47
|
+
fontWeight: "600",
|
|
48
|
+
color: theme.colors.text,
|
|
49
|
+
marginBottom: theme.spacing[2],
|
|
50
|
+
},
|
|
51
|
+
content: {
|
|
52
|
+
gap: theme.spacing[2],
|
|
53
|
+
},
|
|
54
|
+
row: {
|
|
55
|
+
flexDirection: "row",
|
|
56
|
+
gap: theme.spacing[2],
|
|
57
|
+
},
|
|
58
|
+
label: {
|
|
59
|
+
fontSize: 13,
|
|
60
|
+
color: theme.colors.textMuted,
|
|
61
|
+
},
|
|
62
|
+
value: {
|
|
63
|
+
fontSize: 13,
|
|
64
|
+
color: theme.colors.text,
|
|
65
|
+
},
|
|
66
|
+
compactContainer: {
|
|
67
|
+
flexDirection: "row",
|
|
68
|
+
gap: theme.spacing[2],
|
|
69
|
+
flexWrap: "wrap",
|
|
70
|
+
marginTop: theme.spacing[1],
|
|
71
|
+
},
|
|
72
|
+
compactText: {
|
|
73
|
+
fontSize: 14,
|
|
74
|
+
fontWeight: "500",
|
|
75
|
+
color: theme.colors.text,
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentWarnings = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const react_native_1 = require("react-native");
|
|
7
|
+
const metadata_constants_1 = require("../../lib/metadata-constants");
|
|
8
|
+
const theme_1 = require("../../lib/theme/theme");
|
|
9
|
+
const text_1 = require("../ui/text");
|
|
10
|
+
exports.ContentWarnings = (0, react_1.forwardRef)(({ warnings, compact = false }, ref) => {
|
|
11
|
+
const { theme } = (0, theme_1.useTheme)();
|
|
12
|
+
if (!warnings || warnings.length === 0) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const styles = createStyles(theme, compact);
|
|
16
|
+
const getWarningLabel = (warning) => {
|
|
17
|
+
return metadata_constants_1.C2PA_WARNING_LABELS[warning] || warning;
|
|
18
|
+
};
|
|
19
|
+
if (compact) {
|
|
20
|
+
return ((0, jsx_runtime_1.jsx)(react_native_1.View, { ref: ref, style: styles.compactContainer, children: warnings.map((warning, index) => ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.compactWarning, children: (0, jsx_runtime_1.jsx)(text_1.Text, { style: styles.compactWarningText, children: getWarningLabel(warning) }) }, index))) }));
|
|
21
|
+
}
|
|
22
|
+
return ((0, jsx_runtime_1.jsxs)(react_native_1.View, { ref: ref, style: styles.container, children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: styles.title, children: "Content Warnings" }), (0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.warningsContainer, children: warnings.map((warning, index) => ((0, jsx_runtime_1.jsx)(react_native_1.View, { style: styles.warning, children: (0, jsx_runtime_1.jsx)(text_1.Text, { style: styles.warningText, children: getWarningLabel(warning) }) }, index))) })] }));
|
|
23
|
+
});
|
|
24
|
+
exports.ContentWarnings.displayName = "ContentWarnings";
|
|
25
|
+
function createStyles(theme, compact) {
|
|
26
|
+
return react_native_1.StyleSheet.create({
|
|
27
|
+
container: {
|
|
28
|
+
flexDirection: "column",
|
|
29
|
+
gap: theme.spacing[2],
|
|
30
|
+
},
|
|
31
|
+
title: {
|
|
32
|
+
fontSize: 14,
|
|
33
|
+
fontWeight: "600",
|
|
34
|
+
color: theme.colors.text,
|
|
35
|
+
},
|
|
36
|
+
warningsContainer: {
|
|
37
|
+
flexDirection: "row",
|
|
38
|
+
flexWrap: "wrap",
|
|
39
|
+
gap: theme.spacing[2],
|
|
40
|
+
},
|
|
41
|
+
warning: {
|
|
42
|
+
backgroundColor: theme.colors.warning,
|
|
43
|
+
borderRadius: theme.borderRadius.md,
|
|
44
|
+
padding: theme.spacing[2],
|
|
45
|
+
},
|
|
46
|
+
warningText: {
|
|
47
|
+
color: theme.colors.warningForeground,
|
|
48
|
+
fontSize: 12,
|
|
49
|
+
fontWeight: "500",
|
|
50
|
+
},
|
|
51
|
+
compactContainer: {
|
|
52
|
+
flexDirection: "row",
|
|
53
|
+
flexWrap: "wrap",
|
|
54
|
+
gap: theme.spacing[1],
|
|
55
|
+
},
|
|
56
|
+
compactWarning: {
|
|
57
|
+
backgroundColor: theme.colors.warning,
|
|
58
|
+
borderRadius: theme.borderRadius.full,
|
|
59
|
+
paddingHorizontal: 10,
|
|
60
|
+
paddingVertical: 4,
|
|
61
|
+
},
|
|
62
|
+
compactWarningText: {
|
|
63
|
+
color: theme.colors.warningForeground,
|
|
64
|
+
fontSize: 14,
|
|
65
|
+
fontWeight: "600",
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ContentWarnings = exports.ContentRights = exports.ContentMetadataForm = void 0;
|
|
4
|
+
// Main form component
|
|
5
|
+
var content_metadata_form_1 = require("./content-metadata-form");
|
|
6
|
+
Object.defineProperty(exports, "ContentMetadataForm", { enumerable: true, get: function () { return content_metadata_form_1.ContentMetadataForm; } });
|
|
7
|
+
// Display components
|
|
8
|
+
var content_rights_1 = require("./content-rights");
|
|
9
|
+
Object.defineProperty(exports, "ContentRights", { enumerable: true, get: function () { return content_rights_1.ContentRights; } });
|
|
10
|
+
var content_warnings_1 = require("./content-warnings");
|
|
11
|
+
Object.defineProperty(exports, "ContentWarnings", { enumerable: true, get: function () { return content_warnings_1.ContentWarnings; } });
|
|
@@ -18,12 +18,16 @@ function Player(props) {
|
|
|
18
18
|
const setIngest = (0, player_store_1.usePlayerStore)((x) => x.setIngestConnectionState);
|
|
19
19
|
const clearControlsTimeout = (0, player_store_1.usePlayerStore)((x) => x.clearControlsTimeout);
|
|
20
20
|
const setReportingURL = (0, player_store_1.usePlayerStore)((x) => x.setReportingURL);
|
|
21
|
+
const setEmbedded = (0, player_store_1.usePlayerStore)((x) => x.setEmbedded);
|
|
21
22
|
const reportModalOpen = (0, player_store_1.usePlayerStore)((x) => x.reportModalOpen);
|
|
22
23
|
const setReportModalOpen = (0, player_store_1.usePlayerStore)((x) => x.setReportModalOpen);
|
|
23
24
|
const reportSubject = (0, player_store_1.usePlayerStore)((x) => x.reportSubject);
|
|
24
25
|
(0, react_1.useEffect)(() => {
|
|
25
26
|
setReportingURL(props.reportingURL ?? null);
|
|
26
27
|
}, [props.reportingURL]);
|
|
28
|
+
(0, react_1.useEffect)(() => {
|
|
29
|
+
setEmbedded(props.embedded ?? false);
|
|
30
|
+
}, [props.embedded]);
|
|
27
31
|
// Will call back every few seconds to send health updates
|
|
28
32
|
usePlayerStatus();
|
|
29
33
|
(0, react_1.useEffect)(() => {
|