@streamplace/components 0.8.0 → 0.8.5
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 +95 -32
- package/dist/components/mobile-player/rotation-async.native.js +15 -0
- package/dist/components/mobile-player/rotation-lock.js +137 -0
- package/dist/index.js +5 -1
- package/dist/streamplace-store/content-metadata-actions.js +29 -23
- package/dist/streamplace-store/streamplace-store.js +4 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/package.json +4 -2
- package/src/components/content-metadata/content-metadata-form.tsx +228 -96
- package/src/components/content-metadata/index.tsx +0 -8
- package/src/components/mobile-player/rotation-async.native.tsx +15 -0
- package/src/components/mobile-player/rotation-lock.tsx +200 -0
- package/src/index.tsx +10 -0
- package/src/streamplace-store/content-metadata-actions.tsx +32 -29
- package/src/streamplace-store/streamplace-store.tsx +11 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -41,12 +41,16 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
41
41
|
const [contentRights, setContentRights] = (0, react_1.useState)({});
|
|
42
42
|
const [selectedLicense, setSelectedLicense] = (0, react_1.useState)("");
|
|
43
43
|
const [customLicenseText, setCustomLicenseText] = (0, react_1.useState)("");
|
|
44
|
-
const [customDateTime, setCustomDateTime] = (0, react_1.useState)("");
|
|
45
44
|
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
46
45
|
const [hasMetadata, setHasMetadata] = (0, react_1.useState)(false);
|
|
47
46
|
// State for section toggles
|
|
48
47
|
const [activeSection, setActiveSection] = (0, react_1.useState)("contentWarnings");
|
|
49
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);
|
|
50
54
|
// Load existing metadata on mount or from initialMetadata prop
|
|
51
55
|
(0, react_1.useEffect)(() => {
|
|
52
56
|
if (initialMetadata) {
|
|
@@ -56,9 +60,6 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
56
60
|
}
|
|
57
61
|
if (initialMetadata.distributionPolicy) {
|
|
58
62
|
setDistributionPolicy(initialMetadata.distributionPolicy);
|
|
59
|
-
setCustomDateTime(initialMetadata.distributionPolicy.deleteAfter
|
|
60
|
-
? String(initialMetadata.distributionPolicy.deleteAfter)
|
|
61
|
-
: "");
|
|
62
63
|
}
|
|
63
64
|
if (initialMetadata.contentRights) {
|
|
64
65
|
setContentRights(initialMetadata.contentRights);
|
|
@@ -78,9 +79,6 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
78
79
|
}
|
|
79
80
|
if (metadata.record.distributionPolicy) {
|
|
80
81
|
setDistributionPolicy(metadata.record.distributionPolicy);
|
|
81
|
-
setCustomDateTime(metadata.record.distributionPolicy.deleteAfter
|
|
82
|
-
? String(metadata.record.distributionPolicy.deleteAfter)
|
|
83
|
-
: "");
|
|
84
82
|
}
|
|
85
83
|
if (metadata.record.contentRights) {
|
|
86
84
|
setContentRights(metadata.record.contentRights);
|
|
@@ -102,6 +100,7 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
102
100
|
setContentWarnings(newWarnings);
|
|
103
101
|
if (onMetadataChange) {
|
|
104
102
|
onMetadataChange({
|
|
103
|
+
$type: "place.stream.metadata.configuration",
|
|
105
104
|
contentWarnings: { warnings: newWarnings },
|
|
106
105
|
distributionPolicy,
|
|
107
106
|
contentRights,
|
|
@@ -112,6 +111,7 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
112
111
|
(0, react_1.useEffect)(() => {
|
|
113
112
|
if (onMetadataChange) {
|
|
114
113
|
onMetadataChange({
|
|
114
|
+
$type: "place.stream.metadata.configuration",
|
|
115
115
|
contentWarnings: { warnings: contentWarnings },
|
|
116
116
|
distributionPolicy,
|
|
117
117
|
contentRights,
|
|
@@ -119,18 +119,33 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
119
119
|
}
|
|
120
120
|
}, [contentWarnings, distributionPolicy, contentRights, onMetadataChange]);
|
|
121
121
|
// Handle distribution policy changes
|
|
122
|
-
const handleDistributionPolicyChange = (0, react_1.useCallback)((deleteAfter) => {
|
|
123
|
-
let
|
|
124
|
-
|
|
125
|
-
|
|
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
|
+
}
|
|
126
138
|
}
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
139
|
+
if (typeof allowedBroadcasters === "string") {
|
|
140
|
+
newDistributionPolicy.allowedBroadcasters =
|
|
141
|
+
allowedBroadcasters.split("\n");
|
|
142
|
+
}
|
|
143
|
+
setDistributionPolicy(newDistributionPolicy);
|
|
130
144
|
if (onMetadataChange) {
|
|
131
145
|
onMetadataChange({
|
|
146
|
+
$type: "place.stream.metadata.configuration",
|
|
132
147
|
contentWarnings: { warnings: contentWarnings },
|
|
133
|
-
distributionPolicy:
|
|
148
|
+
distributionPolicy: newDistributionPolicy,
|
|
134
149
|
contentRights,
|
|
135
150
|
});
|
|
136
151
|
}
|
|
@@ -147,6 +162,7 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
147
162
|
setContentRights(newRights);
|
|
148
163
|
if (onMetadataChange) {
|
|
149
164
|
onMetadataChange({
|
|
165
|
+
$type: "place.stream.metadata.configuration",
|
|
150
166
|
contentWarnings: { warnings: contentWarnings },
|
|
151
167
|
distributionPolicy,
|
|
152
168
|
contentRights: newRights,
|
|
@@ -157,19 +173,12 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
157
173
|
setLoading(true);
|
|
158
174
|
try {
|
|
159
175
|
// Build the metadata object, only including non-empty fields
|
|
160
|
-
const metadata = {
|
|
176
|
+
const metadata = {
|
|
177
|
+
$type: "place.stream.metadata.configuration",
|
|
178
|
+
};
|
|
161
179
|
// Only include contentWarnings if it has values
|
|
162
180
|
if (contentWarnings && contentWarnings.length > 0) {
|
|
163
|
-
metadata.contentWarnings = contentWarnings;
|
|
164
|
-
}
|
|
165
|
-
// Only include distributionPolicy if it has a deleteAfter value
|
|
166
|
-
const duration = parseInt(customDateTime, 10);
|
|
167
|
-
if (!isNaN(duration) && duration > 0) {
|
|
168
|
-
metadata.distributionPolicy = { deleteAfter: duration };
|
|
169
|
-
setCustomDateTime(`${duration}`);
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
setCustomDateTime("");
|
|
181
|
+
metadata.contentWarnings = { warnings: contentWarnings };
|
|
173
182
|
}
|
|
174
183
|
// Only include contentRights if it has actual values
|
|
175
184
|
const rightsWithLicense = {
|
|
@@ -193,6 +202,17 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
193
202
|
if (Object.keys(filteredRights).length > 0) {
|
|
194
203
|
metadata.contentRights = filteredRights;
|
|
195
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
|
+
}
|
|
196
216
|
await saveContentMetadata(metadata);
|
|
197
217
|
setHasMetadata(true);
|
|
198
218
|
// Show success toast
|
|
@@ -211,7 +231,6 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
211
231
|
contentRights,
|
|
212
232
|
selectedLicense,
|
|
213
233
|
customLicenseText,
|
|
214
|
-
customDateTime,
|
|
215
234
|
hasMetadata,
|
|
216
235
|
saveContentMetadata,
|
|
217
236
|
]);
|
|
@@ -362,7 +381,50 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
362
381
|
], children: [(0, jsx_runtime_1.jsx)(text_1.Text, { style: [
|
|
363
382
|
text.neutral[300],
|
|
364
383
|
{ minWidth: 100, textAlign: "left", paddingBottom: 8 },
|
|
365
|
-
], 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)(
|
|
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: [
|
|
366
428
|
layout.flex.row,
|
|
367
429
|
layout.flex.alignCenter,
|
|
368
430
|
w.percent[100],
|
|
@@ -377,9 +439,10 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
377
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: [
|
|
378
440
|
text.gray[500],
|
|
379
441
|
{ fontSize: 12, paddingBottom: 4 },
|
|
380
|
-
], children: "Duration in seconds (e.g., 300 for 5 minutes)
|
|
381
|
-
|
|
382
|
-
|
|
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
|
+
});
|
|
383
446
|
}, keyboardType: "numeric", variant: "filled", inputStyle: [
|
|
384
447
|
p[3],
|
|
385
448
|
r.md,
|
|
@@ -388,7 +451,7 @@ exports.ContentMetadataForm = (0, react_1.forwardRef)(({ showUpdateButton = fals
|
|
|
388
451
|
borders.width.thin,
|
|
389
452
|
borders.color.neutral[600],
|
|
390
453
|
w.percent[100],
|
|
391
|
-
] })] })] }) })] })), (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: [
|
|
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: [
|
|
392
455
|
bg.primary[500],
|
|
393
456
|
r.md,
|
|
394
457
|
gap.all[3],
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScreenOrientation = exports.isRotationAvailable = void 0;
|
|
4
|
+
let ScreenOrientation = null;
|
|
5
|
+
exports.ScreenOrientation = ScreenOrientation;
|
|
6
|
+
try {
|
|
7
|
+
exports.ScreenOrientation = ScreenOrientation = require("expo-screen-orientation");
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
// expo-screen-orientation not available
|
|
11
|
+
if (__DEV__) {
|
|
12
|
+
console.warn("expo-screen-orientation not installed, rotation features disabled");
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.isRotationAvailable = ScreenOrientation != null;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useRotation = exports.RotationProvider = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const rotation_async_native_1 = require("./rotation-async.native");
|
|
7
|
+
const RotationContext = (0, react_1.createContext)(null);
|
|
8
|
+
const RotationProvider = ({ children, enabled = true, }) => {
|
|
9
|
+
const [isLocked, setIsLocked] = (0, react_1.useState)(false);
|
|
10
|
+
const [canRotate, setCanRotate] = (0, react_1.useState)(rotation_async_native_1.isRotationAvailable);
|
|
11
|
+
const [currentOrientation, setCurrentOrientation] = (0, react_1.useState)(rotation_async_native_1.ScreenOrientation?.Orientation.PORTRAIT_UP ?? 1);
|
|
12
|
+
// If module not available, provide disabled context
|
|
13
|
+
if (!rotation_async_native_1.isRotationAvailable || !rotation_async_native_1.ScreenOrientation) {
|
|
14
|
+
const disabledContextValue = {
|
|
15
|
+
currentOrientation: 1, // Orientation.PORTRAIT_UP
|
|
16
|
+
isLocked: false,
|
|
17
|
+
isActive: false,
|
|
18
|
+
rotateToLandscape: async () => { },
|
|
19
|
+
rotateToPortrait: async () => { },
|
|
20
|
+
toggleRotation: async () => { },
|
|
21
|
+
canRotate: false,
|
|
22
|
+
};
|
|
23
|
+
return ((0, jsx_runtime_1.jsx)(RotationContext.Provider, { value: disabledContextValue, children: children }));
|
|
24
|
+
}
|
|
25
|
+
// Manual rotation functions
|
|
26
|
+
const rotateToLandscape = async () => {
|
|
27
|
+
if (!enabled || !canRotate || !rotation_async_native_1.ScreenOrientation)
|
|
28
|
+
return;
|
|
29
|
+
try {
|
|
30
|
+
await rotation_async_native_1.ScreenOrientation.unlockAsync();
|
|
31
|
+
await rotation_async_native_1.ScreenOrientation.lockAsync(rotation_async_native_1.ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT);
|
|
32
|
+
setIsLocked(true);
|
|
33
|
+
// set current orientation to landscape right
|
|
34
|
+
setCurrentOrientation(rotation_async_native_1.ScreenOrientation.Orientation.LANDSCAPE_RIGHT);
|
|
35
|
+
if (__DEV__) {
|
|
36
|
+
console.log("📲 Manual landscape");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
console.warn("Failed to rotate to landscape:", error);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const rotateToPortrait = async () => {
|
|
44
|
+
if (!enabled || !canRotate || !rotation_async_native_1.ScreenOrientation)
|
|
45
|
+
return;
|
|
46
|
+
try {
|
|
47
|
+
await rotation_async_native_1.ScreenOrientation.unlockAsync();
|
|
48
|
+
await rotation_async_native_1.ScreenOrientation.lockAsync(rotation_async_native_1.ScreenOrientation.OrientationLock.PORTRAIT_UP);
|
|
49
|
+
setIsLocked(true);
|
|
50
|
+
setCurrentOrientation(rotation_async_native_1.ScreenOrientation.Orientation.PORTRAIT_UP);
|
|
51
|
+
if (__DEV__) {
|
|
52
|
+
console.log("📲 Manual portrait");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
console.warn("Failed to rotate to portrait:", error);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
const toggleRotation = async () => {
|
|
60
|
+
if (!rotation_async_native_1.ScreenOrientation)
|
|
61
|
+
return;
|
|
62
|
+
const isLandscape = currentOrientation === rotation_async_native_1.ScreenOrientation.Orientation.LANDSCAPE_LEFT ||
|
|
63
|
+
currentOrientation === rotation_async_native_1.ScreenOrientation.Orientation.LANDSCAPE_RIGHT;
|
|
64
|
+
if (__DEV__) {
|
|
65
|
+
console.log(`🔄 Toggle: current=${currentOrientation}, isLandscape=${isLandscape}`);
|
|
66
|
+
}
|
|
67
|
+
if (isLandscape) {
|
|
68
|
+
await rotateToPortrait();
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
await rotateToLandscape();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
// Track orientation changes
|
|
75
|
+
(0, react_1.useEffect)(() => {
|
|
76
|
+
if (!enabled)
|
|
77
|
+
return;
|
|
78
|
+
const getCurrentOrientation = async () => {
|
|
79
|
+
if (!rotation_async_native_1.ScreenOrientation)
|
|
80
|
+
return;
|
|
81
|
+
try {
|
|
82
|
+
const orient = await rotation_async_native_1.ScreenOrientation.getOrientationAsync();
|
|
83
|
+
setCurrentOrientation(orient);
|
|
84
|
+
if (__DEV__) {
|
|
85
|
+
console.log(`📲 Orientation on load: ${orient}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
console.warn("Failed to get orientation:", error);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
getCurrentOrientation();
|
|
93
|
+
if (!rotation_async_native_1.ScreenOrientation)
|
|
94
|
+
return;
|
|
95
|
+
const subscription = rotation_async_native_1.ScreenOrientation.addOrientationChangeListener((event) => {
|
|
96
|
+
const newOrientation = event.orientationInfo.orientation;
|
|
97
|
+
setCurrentOrientation(newOrientation);
|
|
98
|
+
if (__DEV__) {
|
|
99
|
+
console.log(`🔄 Orientation: ${newOrientation} (locked: ${isLocked})`);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
return () => {
|
|
103
|
+
subscription?.remove();
|
|
104
|
+
if (rotation_async_native_1.ScreenOrientation) {
|
|
105
|
+
rotation_async_native_1.ScreenOrientation.removeOrientationChangeListeners();
|
|
106
|
+
rotation_async_native_1.ScreenOrientation.unlockAsync().catch(() => { });
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}, [enabled]);
|
|
110
|
+
const contextValue = (0, react_1.useMemo)(() => ({
|
|
111
|
+
currentOrientation,
|
|
112
|
+
isLocked,
|
|
113
|
+
isActive: enabled,
|
|
114
|
+
rotateToLandscape,
|
|
115
|
+
rotateToPortrait,
|
|
116
|
+
toggleRotation,
|
|
117
|
+
canRotate,
|
|
118
|
+
}), [
|
|
119
|
+
currentOrientation,
|
|
120
|
+
isLocked,
|
|
121
|
+
enabled,
|
|
122
|
+
canRotate,
|
|
123
|
+
rotateToLandscape,
|
|
124
|
+
rotateToPortrait,
|
|
125
|
+
toggleRotation,
|
|
126
|
+
]);
|
|
127
|
+
return ((0, jsx_runtime_1.jsx)(RotationContext.Provider, { value: contextValue, children: children }));
|
|
128
|
+
};
|
|
129
|
+
exports.RotationProvider = RotationProvider;
|
|
130
|
+
const useRotation = () => {
|
|
131
|
+
const context = (0, react_1.useContext)(RotationContext);
|
|
132
|
+
if (!context) {
|
|
133
|
+
throw new Error("useRotation must be used within a RotationProvider");
|
|
134
|
+
}
|
|
135
|
+
return context;
|
|
136
|
+
};
|
|
137
|
+
exports.useRotation = useRotation;
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.storage = exports.Dashboard = exports.VideoRetry = exports.zero = exports.ui = exports.PlayerUI = exports.Player = exports.usePlayerContext = exports.withPlayerProvider = exports.PlayerProvider = void 0;
|
|
3
|
+
exports.storage = exports.Dashboard = exports.useRotation = exports.RotationProvider = exports.VideoRetry = exports.zero = exports.ui = exports.PlayerUI = exports.Player = exports.usePlayerContext = exports.withPlayerProvider = exports.PlayerProvider = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
// barrel file :)
|
|
6
6
|
require("./crypto-polyfill");
|
|
@@ -29,6 +29,10 @@ tslib_1.__exportStar(require("./components/chat/system-message"), exports);
|
|
|
29
29
|
var video_retry_1 = require("./components/mobile-player/video-retry");
|
|
30
30
|
Object.defineProperty(exports, "VideoRetry", { enumerable: true, get: function () { return tslib_1.__importDefault(video_retry_1).default; } });
|
|
31
31
|
tslib_1.__exportStar(require("./lib/system-messages"), exports);
|
|
32
|
+
// Rotation lock system exports
|
|
33
|
+
var rotation_lock_1 = require("./components/mobile-player/rotation-lock");
|
|
34
|
+
Object.defineProperty(exports, "RotationProvider", { enumerable: true, get: function () { return rotation_lock_1.RotationProvider; } });
|
|
35
|
+
Object.defineProperty(exports, "useRotation", { enumerable: true, get: function () { return rotation_lock_1.useRotation; } });
|
|
32
36
|
tslib_1.__exportStar(require("./components/share/sharesheet"), exports);
|
|
33
37
|
tslib_1.__exportStar(require("./components/keep-awake"), exports);
|
|
34
38
|
// Dashboard components
|
|
@@ -1,46 +1,52 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useGetContentMetadata = exports.useSaveContentMetadata = void 0;
|
|
3
|
+
exports.useGetContentMetadata = exports.useSaveContentMetadata = exports.useGetBroadcasterDID = void 0;
|
|
4
4
|
const streamplace_store_1 = require("./streamplace-store");
|
|
5
5
|
const xrpc_1 = require("./xrpc");
|
|
6
|
+
const useGetBroadcasterDID = () => {
|
|
7
|
+
const pdsAgent = (0, xrpc_1.usePDSAgent)();
|
|
8
|
+
const did = (0, streamplace_store_1.useDID)();
|
|
9
|
+
const setBroadcasterDID = (0, streamplace_store_1.useStreamplaceStore)((state) => state.setBroadcasterDID);
|
|
10
|
+
const setServerDID = (0, streamplace_store_1.useStreamplaceStore)((state) => state.setServerDID);
|
|
11
|
+
return async () => {
|
|
12
|
+
if (!pdsAgent || !did) {
|
|
13
|
+
throw new Error("No PDS agent or DID available");
|
|
14
|
+
}
|
|
15
|
+
const result = await pdsAgent.place.stream.broadcast.getBroadcaster();
|
|
16
|
+
if (!result.success) {
|
|
17
|
+
throw new Error("Failed to get broadcaster DID");
|
|
18
|
+
}
|
|
19
|
+
setBroadcasterDID(result.data.broadcaster);
|
|
20
|
+
if (result.data.server) {
|
|
21
|
+
setServerDID(result.data.server);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
setServerDID(null);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
exports.useGetBroadcasterDID = useGetBroadcasterDID;
|
|
6
29
|
const useSaveContentMetadata = () => {
|
|
7
30
|
const pdsAgent = (0, xrpc_1.usePDSAgent)();
|
|
8
31
|
const did = (0, streamplace_store_1.useDID)();
|
|
9
32
|
const setContentMetadata = (0, streamplace_store_1.useSetContentMetadata)();
|
|
10
|
-
return async (
|
|
33
|
+
return async (metadataRecord) => {
|
|
11
34
|
if (!pdsAgent || !did) {
|
|
12
35
|
throw new Error("No PDS agent or DID available");
|
|
13
36
|
}
|
|
14
|
-
const metadataRecord = {
|
|
15
|
-
$type: "place.stream.metadata.configuration",
|
|
16
|
-
createdAt: new Date().toISOString(),
|
|
17
|
-
...(params.contentWarnings &&
|
|
18
|
-
params.contentWarnings.length > 0 && {
|
|
19
|
-
contentWarnings: { warnings: params.contentWarnings },
|
|
20
|
-
}),
|
|
21
|
-
...(params.distributionPolicy &&
|
|
22
|
-
params.distributionPolicy.deleteAfter && {
|
|
23
|
-
distributionPolicy: params.distributionPolicy,
|
|
24
|
-
}),
|
|
25
|
-
...(params.contentRights &&
|
|
26
|
-
Object.keys(params.contentRights).length > 0 && {
|
|
27
|
-
contentRights: params.contentRights,
|
|
28
|
-
}),
|
|
29
|
-
};
|
|
30
|
-
const rkey = params.rkey || "self";
|
|
31
37
|
try {
|
|
32
38
|
// Try to update existing record first
|
|
33
39
|
const result = await pdsAgent.com.atproto.repo.putRecord({
|
|
34
40
|
repo: did,
|
|
35
41
|
collection: "place.stream.metadata.configuration",
|
|
36
|
-
rkey,
|
|
42
|
+
rkey: "self",
|
|
37
43
|
record: metadataRecord,
|
|
38
44
|
});
|
|
39
45
|
const contentMetadata = {
|
|
40
46
|
record: metadataRecord,
|
|
41
47
|
uri: result.data.uri,
|
|
42
48
|
cid: result.data.cid || "",
|
|
43
|
-
rkey,
|
|
49
|
+
rkey: "self",
|
|
44
50
|
};
|
|
45
51
|
setContentMetadata(contentMetadata);
|
|
46
52
|
return contentMetadata;
|
|
@@ -55,14 +61,14 @@ const useSaveContentMetadata = () => {
|
|
|
55
61
|
const createResult = await pdsAgent.com.atproto.repo.createRecord({
|
|
56
62
|
repo: did,
|
|
57
63
|
collection: "place.stream.metadata.configuration",
|
|
58
|
-
rkey,
|
|
64
|
+
rkey: "self",
|
|
59
65
|
record: metadataRecord,
|
|
60
66
|
});
|
|
61
67
|
const contentMetadata = {
|
|
62
68
|
record: metadataRecord,
|
|
63
69
|
uri: createResult.data.uri,
|
|
64
70
|
cid: createResult.data.cid || "",
|
|
65
|
-
rkey,
|
|
71
|
+
rkey: "self",
|
|
66
72
|
};
|
|
67
73
|
setContentMetadata(contentMetadata);
|
|
68
74
|
return contentMetadata;
|
|
@@ -25,6 +25,10 @@ const makeStreamplaceStore = ({ url, }) => {
|
|
|
25
25
|
oauthSession: null,
|
|
26
26
|
handle: null,
|
|
27
27
|
chatProfile: null,
|
|
28
|
+
broadcasterDID: null,
|
|
29
|
+
setBroadcasterDID: (broadcasterDID) => set({ broadcasterDID }),
|
|
30
|
+
serverDID: null,
|
|
31
|
+
setServerDID: (serverDID) => set({ serverDID }),
|
|
28
32
|
// Content metadata
|
|
29
33
|
contentMetadata: null,
|
|
30
34
|
setContentMetadata: (metadata) => set({ contentMetadata: metadata }),
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@streamplace/components",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"description": "Streamplace React (Native) Components",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "src/index.tsx",
|
|
@@ -30,6 +30,8 @@
|
|
|
30
30
|
"@rn-primitives/slider": "^1.2.0",
|
|
31
31
|
"class-variance-authority": "^0.6.1",
|
|
32
32
|
"expo-keep-awake": "^14.0.0",
|
|
33
|
+
"expo-screen-orientation": "^9.0.7",
|
|
34
|
+
"expo-sensors": "^15.0.7",
|
|
33
35
|
"expo-sqlite": "~15.2.12",
|
|
34
36
|
"expo-video": "^2.0.0",
|
|
35
37
|
"hls.js": "^1.5.17",
|
|
@@ -54,5 +56,5 @@
|
|
|
54
56
|
"start": "tsc --watch --preserveWatchOutput",
|
|
55
57
|
"prepare": "tsc"
|
|
56
58
|
},
|
|
57
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "baa713714aac33e98c399f92ce12268a1aac3ef6"
|
|
58
60
|
}
|