@streamplace/components 0.8.18 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/chat/chat-box.d.ts +1 -1
- package/dist/components/chat/chat-box.d.ts.map +1 -1
- package/dist/components/chat/chat-box.js +3 -0
- package/dist/components/chat/chat-box.js.map +1 -1
- package/dist/components/chat/mod-view.d.ts +4 -2
- package/dist/components/chat/mod-view.d.ts.map +1 -1
- package/dist/components/chat/mod-view.js +142 -42
- package/dist/components/chat/mod-view.js.map +1 -1
- package/dist/components/dashboard/chat-panel.d.ts +2 -1
- package/dist/components/dashboard/chat-panel.d.ts.map +1 -1
- package/dist/components/dashboard/chat-panel.js +2 -3
- package/dist/components/dashboard/chat-panel.js.map +1 -1
- package/dist/components/dashboard/index.d.ts +1 -0
- package/dist/components/dashboard/index.d.ts.map +1 -1
- package/dist/components/dashboard/index.js +3 -1
- package/dist/components/dashboard/index.js.map +1 -1
- package/dist/components/dashboard/moderator-panel.d.ts +7 -0
- package/dist/components/dashboard/moderator-panel.d.ts.map +1 -0
- package/dist/components/dashboard/moderator-panel.js +256 -0
- package/dist/components/dashboard/moderator-panel.js.map +1 -0
- package/dist/components/ui/dialog.d.ts +1 -1
- package/dist/components/ui/menu.d.ts.map +1 -1
- package/dist/components/ui/menu.js +2 -2
- package/dist/components/ui/menu.js.map +1 -1
- package/dist/crypto-polyfill.native.js +7 -1
- package/dist/crypto-polyfill.native.js.map +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/useDocumentTitle.d.ts +6 -0
- package/dist/hooks/useDocumentTitle.d.ts.map +1 -0
- package/dist/hooks/useDocumentTitle.js +40 -0
- package/dist/hooks/useDocumentTitle.js.map +1 -0
- package/dist/lib/theme/atoms.d.ts +138 -138
- package/dist/lib/theme/branded-theme-provider.d.ts +13 -0
- package/dist/lib/theme/branded-theme-provider.d.ts.map +1 -0
- package/dist/lib/theme/branded-theme-provider.js +34 -0
- package/dist/lib/theme/branded-theme-provider.js.map +1 -0
- package/dist/lib/theme/index.d.ts +1 -0
- package/dist/lib/theme/index.d.ts.map +1 -1
- package/dist/lib/theme/index.js +4 -1
- package/dist/lib/theme/index.js.map +1 -1
- package/dist/livestream-store/chat.d.ts +1 -1
- package/dist/livestream-store/chat.d.ts.map +1 -1
- package/dist/livestream-store/chat.js +1 -3
- package/dist/livestream-store/chat.js.map +1 -1
- package/dist/livestream-store/livestream-state.d.ts +3 -1
- package/dist/livestream-store/livestream-state.d.ts.map +1 -1
- package/dist/livestream-store/livestream-store.d.ts.map +1 -1
- package/dist/livestream-store/livestream-store.js +2 -0
- package/dist/livestream-store/livestream-store.js.map +1 -1
- package/dist/livestream-store/stream-key.d.ts +1 -0
- package/dist/livestream-store/stream-key.d.ts.map +1 -1
- package/dist/livestream-store/stream-key.js +2 -0
- package/dist/livestream-store/stream-key.js.map +1 -1
- package/dist/livestream-store/websocket-consumer.d.ts.map +1 -1
- package/dist/livestream-store/websocket-consumer.js +48 -0
- package/dist/livestream-store/websocket-consumer.js.map +1 -1
- package/dist/streamplace-provider/index.d.ts +3 -0
- package/dist/streamplace-provider/index.d.ts.map +1 -1
- package/dist/streamplace-provider/index.js +12 -1
- package/dist/streamplace-provider/index.js.map +1 -1
- package/dist/streamplace-store/block.d.ts +36 -2
- package/dist/streamplace-store/block.d.ts.map +1 -1
- package/dist/streamplace-store/block.js +121 -18
- package/dist/streamplace-store/block.js.map +1 -1
- package/dist/streamplace-store/branding.d.ts +27 -0
- package/dist/streamplace-store/branding.d.ts.map +1 -0
- package/dist/streamplace-store/branding.js +195 -0
- package/dist/streamplace-store/branding.js.map +1 -0
- package/dist/streamplace-store/index.d.ts +4 -0
- package/dist/streamplace-store/index.d.ts.map +1 -1
- package/dist/streamplace-store/index.js +4 -0
- package/dist/streamplace-store/index.js.map +1 -1
- package/dist/streamplace-store/moderation.d.ts +16 -0
- package/dist/streamplace-store/moderation.d.ts.map +1 -0
- package/dist/streamplace-store/moderation.js +141 -0
- package/dist/streamplace-store/moderation.js.map +1 -0
- package/dist/streamplace-store/moderator-management.d.ts +44 -0
- package/dist/streamplace-store/moderator-management.d.ts.map +1 -0
- package/dist/streamplace-store/moderator-management.js +136 -0
- package/dist/streamplace-store/moderator-management.js.map +1 -0
- package/dist/streamplace-store/streamplace-store.d.ts +6 -0
- package/dist/streamplace-store/streamplace-store.d.ts.map +1 -1
- package/dist/streamplace-store/streamplace-store.js +6 -0
- package/dist/streamplace-store/streamplace-store.js.map +1 -1
- package/dist/streamplace-store/xrpc.d.ts +1 -0
- package/dist/streamplace-store/xrpc.d.ts.map +1 -1
- package/dist/streamplace-store/xrpc.js +16 -0
- package/dist/streamplace-store/xrpc.js.map +1 -1
- package/locales/en-US/settings.ftl +91 -0
- package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
- package/package.json +3 -3
- package/src/components/chat/chat-box.tsx +3 -1
- package/src/components/chat/mod-view.tsx +431 -121
- package/src/components/dashboard/chat-panel.tsx +2 -1
- package/src/components/dashboard/index.tsx +1 -0
- package/src/components/dashboard/moderator-panel.tsx +632 -0
- package/src/components/ui/menu.tsx +1 -2
- package/src/crypto-polyfill.native.tsx +8 -1
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useDocumentTitle.tsx +45 -0
- package/src/lib/theme/branded-theme-provider.tsx +58 -0
- package/src/lib/theme/index.ts +3 -0
- package/src/livestream-store/chat.tsx +0 -2
- package/src/livestream-store/livestream-state.tsx +5 -0
- package/src/livestream-store/livestream-store.tsx +2 -0
- package/src/livestream-store/stream-key.tsx +3 -0
- package/src/livestream-store/websocket-consumer.tsx +60 -0
- package/src/streamplace-provider/index.tsx +23 -4
- package/src/streamplace-store/block.tsx +139 -19
- package/src/streamplace-store/branding.tsx +216 -0
- package/src/streamplace-store/index.tsx +4 -0
- package/src/streamplace-store/moderation.tsx +185 -0
- package/src/streamplace-store/moderator-management.tsx +175 -0
- package/src/streamplace-store/streamplace-store.tsx +15 -0
- package/src/streamplace-store/xrpc.tsx +18 -1
- package/dist/assets/emoji-data.json +0 -19371
- package/src/assets/emoji-data.json +0 -19371
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { PlaceStreamModerationPermission } from "streamplace";
|
|
3
|
+
import { useLivestreamStore } from "../livestream-store/livestream-store";
|
|
4
|
+
import { usePDSAgent } from "./xrpc";
|
|
5
|
+
|
|
6
|
+
export interface ModerationPermissions {
|
|
7
|
+
canBan: boolean;
|
|
8
|
+
canHide: boolean;
|
|
9
|
+
canManageLivestream: boolean;
|
|
10
|
+
isOwner: boolean;
|
|
11
|
+
isLoading: boolean;
|
|
12
|
+
error: string | null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Hook to check if the current user can moderate for a given streamer.
|
|
17
|
+
* Returns permission flags based on:
|
|
18
|
+
* - Owner: full permissions if userDID === streamerDID
|
|
19
|
+
* - Delegated: permissions from place.stream.moderation.permission records
|
|
20
|
+
*/
|
|
21
|
+
export function useCanModerate(
|
|
22
|
+
streamerDID: string | null | undefined,
|
|
23
|
+
): ModerationPermissions {
|
|
24
|
+
const agent = usePDSAgent();
|
|
25
|
+
const userDID = agent?.did;
|
|
26
|
+
|
|
27
|
+
// Get moderation permissions from livestream store (updated via WebSocket)
|
|
28
|
+
const moderationPermissions = useLivestreamStore(
|
|
29
|
+
(state) => state.moderationPermissions,
|
|
30
|
+
);
|
|
31
|
+
const setModerationPermissions = useLivestreamStore(
|
|
32
|
+
(state) => state.setModerationPermissions,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const [isOwner, setIsOwner] = useState(false);
|
|
36
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
37
|
+
const [error, setError] = useState<string | null>(null);
|
|
38
|
+
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
if (!userDID || !streamerDID) {
|
|
41
|
+
setModerationPermissions([]);
|
|
42
|
+
setIsOwner(false);
|
|
43
|
+
setError(null);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// If user is the streamer, they have full permissions
|
|
48
|
+
if (userDID === streamerDID) {
|
|
49
|
+
setIsOwner(true);
|
|
50
|
+
setModerationPermissions([]); // Not needed for owner
|
|
51
|
+
setIsLoading(false);
|
|
52
|
+
setError(null);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Otherwise, fetch delegation records from the streamer's repo
|
|
57
|
+
// This initial fetch populates the store, then WebSocket updates will keep it in sync
|
|
58
|
+
const fetchDelegation = async () => {
|
|
59
|
+
if (!agent) {
|
|
60
|
+
setModerationPermissions([]);
|
|
61
|
+
setIsLoading(false);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
setIsLoading(true);
|
|
66
|
+
setError(null);
|
|
67
|
+
setIsOwner(false);
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
// Use authenticated agent to list permission records from the streamer's repo
|
|
71
|
+
const result = await agent.com.atproto.repo.listRecords({
|
|
72
|
+
repo: streamerDID,
|
|
73
|
+
collection: "place.stream.moderation.permission",
|
|
74
|
+
limit: 100,
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const records = result.data.records || [];
|
|
78
|
+
const permissionRecords: PlaceStreamModerationPermission.Record[] =
|
|
79
|
+
records
|
|
80
|
+
.map((r: { value: any }) => r.value)
|
|
81
|
+
.filter(
|
|
82
|
+
(v: any) => v && v.$type === "place.stream.moderation.permission",
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
// Store all permissions in the livestream store
|
|
86
|
+
// WebSocket updates will keep this in sync
|
|
87
|
+
setModerationPermissions(permissionRecords);
|
|
88
|
+
} catch (err) {
|
|
89
|
+
console.error("[useCanModerate] Error fetching permissions:", err);
|
|
90
|
+
setError(
|
|
91
|
+
`Could not fetch moderation permissions: ${err instanceof Error ? err.message : `Unknown error: ${err}`}`,
|
|
92
|
+
);
|
|
93
|
+
setModerationPermissions([]);
|
|
94
|
+
} finally {
|
|
95
|
+
setIsLoading(false);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
// Fetch immediately on mount or when dependencies change
|
|
100
|
+
fetchDelegation();
|
|
101
|
+
}, [userDID, streamerDID, agent, setModerationPermissions]);
|
|
102
|
+
|
|
103
|
+
// If permissions were cleared (e.g., due to deletion), trigger a refetch
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
// If permissions were cleared and we're not the owner, refetch
|
|
106
|
+
if (
|
|
107
|
+
moderationPermissions.length === 0 &&
|
|
108
|
+
!isOwner &&
|
|
109
|
+
userDID &&
|
|
110
|
+
streamerDID &&
|
|
111
|
+
agent
|
|
112
|
+
) {
|
|
113
|
+
const fetchDelegation = async () => {
|
|
114
|
+
try {
|
|
115
|
+
const result = await agent.com.atproto.repo.listRecords({
|
|
116
|
+
repo: streamerDID,
|
|
117
|
+
collection: "place.stream.moderation.permission",
|
|
118
|
+
limit: 100,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const records = result.data.records || [];
|
|
122
|
+
const permissionRecords: PlaceStreamModerationPermission.Record[] =
|
|
123
|
+
records
|
|
124
|
+
.map((r: { value: any }) => r.value)
|
|
125
|
+
.filter(
|
|
126
|
+
(v: any) =>
|
|
127
|
+
v && v.$type === "place.stream.moderation.permission",
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
setModerationPermissions(permissionRecords);
|
|
131
|
+
} catch (err) {
|
|
132
|
+
console.error("[useCanModerate] Error refetching permissions:", err);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// Small delay to avoid rapid refetches
|
|
137
|
+
const timeout = setTimeout(fetchDelegation, 100);
|
|
138
|
+
return () => clearTimeout(timeout);
|
|
139
|
+
}
|
|
140
|
+
}, [
|
|
141
|
+
moderationPermissions.length,
|
|
142
|
+
isOwner,
|
|
143
|
+
userDID,
|
|
144
|
+
streamerDID,
|
|
145
|
+
agent,
|
|
146
|
+
setModerationPermissions,
|
|
147
|
+
]);
|
|
148
|
+
|
|
149
|
+
// Find ALL delegation records for this moderator and merge their permissions
|
|
150
|
+
const delegations = moderationPermissions.filter(
|
|
151
|
+
(perm) => perm.moderator === userDID,
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
// Merge permissions from all delegation records for this moderator
|
|
155
|
+
const permissions: string[] = delegations.reduce(
|
|
156
|
+
(acc: string[], delegation) => {
|
|
157
|
+
// Check if delegation has expired
|
|
158
|
+
if (delegation.expirationTime) {
|
|
159
|
+
const expiration = new Date(delegation.expirationTime);
|
|
160
|
+
if (new Date() > expiration) {
|
|
161
|
+
return acc; // Skip expired delegations
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Add all permissions from this delegation, avoiding duplicates
|
|
166
|
+
const delegationPerms = delegation.permissions || [];
|
|
167
|
+
for (const perm of delegationPerms) {
|
|
168
|
+
if (!acc.includes(perm)) {
|
|
169
|
+
acc.push(perm);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return acc;
|
|
173
|
+
},
|
|
174
|
+
[],
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
return {
|
|
178
|
+
canBan: isOwner || permissions.includes("ban"),
|
|
179
|
+
canHide: isOwner || permissions.includes("hide"),
|
|
180
|
+
canManageLivestream: isOwner || permissions.includes("livestream.manage"),
|
|
181
|
+
isOwner,
|
|
182
|
+
isLoading,
|
|
183
|
+
error,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from "react";
|
|
2
|
+
import { PlaceStreamModerationPermission } from "streamplace";
|
|
3
|
+
import { usePDSAgent } from "./xrpc";
|
|
4
|
+
|
|
5
|
+
interface ModeratorRecord {
|
|
6
|
+
uri: string;
|
|
7
|
+
cid: string;
|
|
8
|
+
value: PlaceStreamModerationPermission.Record;
|
|
9
|
+
rkey: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ListModeratorsResult {
|
|
13
|
+
moderators: ModeratorRecord[];
|
|
14
|
+
isLoading: boolean;
|
|
15
|
+
error: string | null;
|
|
16
|
+
refresh: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Hook to list all moderators for the current user's stream.
|
|
21
|
+
* Fetches place.stream.moderation.permission records from the user's repo.
|
|
22
|
+
*/
|
|
23
|
+
export function useListModerators(): ListModeratorsResult {
|
|
24
|
+
const agent = usePDSAgent();
|
|
25
|
+
const [moderators, setModerators] = useState<ModeratorRecord[]>([]);
|
|
26
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
27
|
+
const [error, setError] = useState<string | null>(null);
|
|
28
|
+
const [refreshTrigger, setRefreshTrigger] = useState(0);
|
|
29
|
+
|
|
30
|
+
const refresh = useCallback(() => {
|
|
31
|
+
setRefreshTrigger((prev) => prev + 1);
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
if (!agent?.did) {
|
|
36
|
+
setModerators([]);
|
|
37
|
+
setError(null);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const fetchModerators = async () => {
|
|
42
|
+
setIsLoading(true);
|
|
43
|
+
setError(null);
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const result = await agent.place.stream.moderation.permission.list({
|
|
47
|
+
repo: agent.did!,
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const records = result.records.map((record: any) => {
|
|
51
|
+
const rkey = record.uri.split("/").pop();
|
|
52
|
+
return {
|
|
53
|
+
uri: record.uri,
|
|
54
|
+
cid: record.cid || "",
|
|
55
|
+
value: record.value,
|
|
56
|
+
rkey: rkey || "",
|
|
57
|
+
};
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
setModerators(records);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
setError(
|
|
63
|
+
`Failed to fetch moderators: ${err instanceof Error ? err.message : "Unknown error"}`,
|
|
64
|
+
);
|
|
65
|
+
setModerators([]);
|
|
66
|
+
} finally {
|
|
67
|
+
setIsLoading(false);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
fetchModerators();
|
|
72
|
+
}, [agent?.did, refreshTrigger]);
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
moderators,
|
|
76
|
+
isLoading,
|
|
77
|
+
error,
|
|
78
|
+
refresh,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface AddModeratorParams {
|
|
83
|
+
moderatorDID: string;
|
|
84
|
+
permissions: ("ban" | "hide" | "livestream.manage")[];
|
|
85
|
+
expirationTime?: string; // ISO 8601 datetime string
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Hook to add a new moderator.
|
|
90
|
+
* Creates a place.stream.moderation.permission record in the current user's repo.
|
|
91
|
+
*/
|
|
92
|
+
export function useAddModerator() {
|
|
93
|
+
const agent = usePDSAgent();
|
|
94
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
95
|
+
|
|
96
|
+
const addModerator = async (params: AddModeratorParams) => {
|
|
97
|
+
if (!agent?.did) {
|
|
98
|
+
throw new Error("Not logged in");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (params.permissions.length === 0) {
|
|
102
|
+
throw new Error("At least one permission must be selected");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
setIsLoading(true);
|
|
106
|
+
try {
|
|
107
|
+
// Resolve handle to DID if needed
|
|
108
|
+
let moderatorDID = params.moderatorDID.trim();
|
|
109
|
+
if (!moderatorDID.startsWith("did:")) {
|
|
110
|
+
if (moderatorDID.startsWith("@")) {
|
|
111
|
+
moderatorDID = moderatorDID.substring(1); // Remove @
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const resolved = await agent.com.atproto.identity.resolveHandle({
|
|
115
|
+
handle: moderatorDID,
|
|
116
|
+
});
|
|
117
|
+
moderatorDID = resolved.data.did;
|
|
118
|
+
} catch (e) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
`Invalid DID or handle: ${moderatorDID}. Please use a valid DID (did:plc:...) or handle (@handle.bsky.social)`,
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const record: PlaceStreamModerationPermission.Record = {
|
|
126
|
+
$type: "place.stream.moderation.permission",
|
|
127
|
+
moderator: moderatorDID,
|
|
128
|
+
permissions: params.permissions,
|
|
129
|
+
createdAt: new Date().toISOString(),
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
if (params.expirationTime) {
|
|
133
|
+
(record as any).expirationTime = params.expirationTime;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const result = await agent.place.stream.moderation.permission.create(
|
|
137
|
+
{ repo: agent.did },
|
|
138
|
+
record,
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
return result;
|
|
142
|
+
} finally {
|
|
143
|
+
setIsLoading(false);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
return { addModerator, isLoading };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Hook to remove a moderator.
|
|
152
|
+
* Deletes a place.stream.moderation.permission record by its rkey.
|
|
153
|
+
*/
|
|
154
|
+
export function useRemoveModerator() {
|
|
155
|
+
const agent = usePDSAgent();
|
|
156
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
157
|
+
|
|
158
|
+
const removeModerator = async (rkey: string) => {
|
|
159
|
+
if (!agent?.did) {
|
|
160
|
+
throw new Error("Not logged in");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
setIsLoading(true);
|
|
164
|
+
try {
|
|
165
|
+
await agent.place.stream.moderation.permission.delete({
|
|
166
|
+
repo: agent.did,
|
|
167
|
+
rkey,
|
|
168
|
+
});
|
|
169
|
+
} finally {
|
|
170
|
+
setIsLoading(false);
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
return { removeModerator, isLoading };
|
|
175
|
+
}
|
|
@@ -4,6 +4,7 @@ import { PlaceStreamChatProfile, PlaceStreamLivestream } from "streamplace";
|
|
|
4
4
|
import { createStore, StoreApi, useStore } from "zustand";
|
|
5
5
|
import storage from "../storage";
|
|
6
6
|
import { StreamplaceContext } from "../streamplace-provider/context";
|
|
7
|
+
import { BrandingAsset } from "./branding";
|
|
7
8
|
|
|
8
9
|
export interface ContentMetadataResult {
|
|
9
10
|
record: any;
|
|
@@ -48,6 +49,13 @@ export interface StreamplaceState {
|
|
|
48
49
|
setBroadcasterDID: (broadcasterDID: string | null) => void;
|
|
49
50
|
serverDID: string | null;
|
|
50
51
|
setServerDID: (serverDID: string | null) => void;
|
|
52
|
+
adminDIDs: string[];
|
|
53
|
+
setAdminDIDs: (adminDIDs: string[]) => void;
|
|
54
|
+
|
|
55
|
+
// Branding state
|
|
56
|
+
branding: Record<string, BrandingAsset> | null;
|
|
57
|
+
brandingLoading: boolean;
|
|
58
|
+
brandingError: string | null;
|
|
51
59
|
|
|
52
60
|
// Volume state
|
|
53
61
|
volume: number;
|
|
@@ -111,11 +119,18 @@ export const makeStreamplaceStore = ({
|
|
|
111
119
|
set({ broadcasterDID }),
|
|
112
120
|
serverDID: null,
|
|
113
121
|
setServerDID: (serverDID: string | null) => set({ serverDID }),
|
|
122
|
+
adminDIDs: [],
|
|
123
|
+
setAdminDIDs: (adminDIDs: string[]) => set({ adminDIDs }),
|
|
114
124
|
|
|
115
125
|
// Content metadata
|
|
116
126
|
contentMetadata: null,
|
|
117
127
|
setContentMetadata: (metadata) => set({ contentMetadata: metadata }),
|
|
118
128
|
|
|
129
|
+
// Branding state
|
|
130
|
+
branding: null,
|
|
131
|
+
brandingLoading: false,
|
|
132
|
+
brandingError: null,
|
|
133
|
+
|
|
119
134
|
// Volume state - start with defaults
|
|
120
135
|
volume: 1.0,
|
|
121
136
|
muted: false,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useMemo } from "react";
|
|
2
2
|
import { StreamplaceAgent } from "streamplace";
|
|
3
|
-
import { useStreamplaceStore } from ".";
|
|
3
|
+
import { useStreamplaceStore, useUrl } from ".";
|
|
4
4
|
|
|
5
5
|
export function usePDSAgent(): StreamplaceAgent | null {
|
|
6
6
|
const oauthSession = useStreamplaceStore((state) => state.oauthSession);
|
|
@@ -20,3 +20,20 @@ export function usePDSAgent(): StreamplaceAgent | null {
|
|
|
20
20
|
return new StreamplaceAgent(oauthSession);
|
|
21
21
|
}, [oauthSession]);
|
|
22
22
|
}
|
|
23
|
+
|
|
24
|
+
// can be unauthed, but will always use the current node URL
|
|
25
|
+
export function usePossiblyUnauthedPDSAgent(): StreamplaceAgent | null {
|
|
26
|
+
const nodeUrl = useUrl();
|
|
27
|
+
const oauthSession = useStreamplaceStore((state) => state.oauthSession);
|
|
28
|
+
// oauthsession is
|
|
29
|
+
// - undefined when loading
|
|
30
|
+
// - null when logged out, and
|
|
31
|
+
// - SessionManager when logged in
|
|
32
|
+
return useMemo(() => {
|
|
33
|
+
if (!oauthSession) {
|
|
34
|
+
return new StreamplaceAgent(nodeUrl);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return new StreamplaceAgent(oauthSession);
|
|
38
|
+
}, [oauthSession]);
|
|
39
|
+
}
|