@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.
Files changed (120) hide show
  1. package/dist/components/chat/chat-box.d.ts +1 -1
  2. package/dist/components/chat/chat-box.d.ts.map +1 -1
  3. package/dist/components/chat/chat-box.js +3 -0
  4. package/dist/components/chat/chat-box.js.map +1 -1
  5. package/dist/components/chat/mod-view.d.ts +4 -2
  6. package/dist/components/chat/mod-view.d.ts.map +1 -1
  7. package/dist/components/chat/mod-view.js +142 -42
  8. package/dist/components/chat/mod-view.js.map +1 -1
  9. package/dist/components/dashboard/chat-panel.d.ts +2 -1
  10. package/dist/components/dashboard/chat-panel.d.ts.map +1 -1
  11. package/dist/components/dashboard/chat-panel.js +2 -3
  12. package/dist/components/dashboard/chat-panel.js.map +1 -1
  13. package/dist/components/dashboard/index.d.ts +1 -0
  14. package/dist/components/dashboard/index.d.ts.map +1 -1
  15. package/dist/components/dashboard/index.js +3 -1
  16. package/dist/components/dashboard/index.js.map +1 -1
  17. package/dist/components/dashboard/moderator-panel.d.ts +7 -0
  18. package/dist/components/dashboard/moderator-panel.d.ts.map +1 -0
  19. package/dist/components/dashboard/moderator-panel.js +256 -0
  20. package/dist/components/dashboard/moderator-panel.js.map +1 -0
  21. package/dist/components/ui/dialog.d.ts +1 -1
  22. package/dist/components/ui/menu.d.ts.map +1 -1
  23. package/dist/components/ui/menu.js +2 -2
  24. package/dist/components/ui/menu.js.map +1 -1
  25. package/dist/crypto-polyfill.native.js +7 -1
  26. package/dist/crypto-polyfill.native.js.map +1 -1
  27. package/dist/hooks/index.d.ts +1 -0
  28. package/dist/hooks/index.d.ts.map +1 -1
  29. package/dist/hooks/index.js +1 -0
  30. package/dist/hooks/index.js.map +1 -1
  31. package/dist/hooks/useDocumentTitle.d.ts +6 -0
  32. package/dist/hooks/useDocumentTitle.d.ts.map +1 -0
  33. package/dist/hooks/useDocumentTitle.js +40 -0
  34. package/dist/hooks/useDocumentTitle.js.map +1 -0
  35. package/dist/lib/theme/atoms.d.ts +138 -138
  36. package/dist/lib/theme/branded-theme-provider.d.ts +13 -0
  37. package/dist/lib/theme/branded-theme-provider.d.ts.map +1 -0
  38. package/dist/lib/theme/branded-theme-provider.js +34 -0
  39. package/dist/lib/theme/branded-theme-provider.js.map +1 -0
  40. package/dist/lib/theme/index.d.ts +1 -0
  41. package/dist/lib/theme/index.d.ts.map +1 -1
  42. package/dist/lib/theme/index.js +4 -1
  43. package/dist/lib/theme/index.js.map +1 -1
  44. package/dist/livestream-store/chat.d.ts +1 -1
  45. package/dist/livestream-store/chat.d.ts.map +1 -1
  46. package/dist/livestream-store/chat.js +1 -3
  47. package/dist/livestream-store/chat.js.map +1 -1
  48. package/dist/livestream-store/livestream-state.d.ts +3 -1
  49. package/dist/livestream-store/livestream-state.d.ts.map +1 -1
  50. package/dist/livestream-store/livestream-store.d.ts.map +1 -1
  51. package/dist/livestream-store/livestream-store.js +2 -0
  52. package/dist/livestream-store/livestream-store.js.map +1 -1
  53. package/dist/livestream-store/stream-key.d.ts +1 -0
  54. package/dist/livestream-store/stream-key.d.ts.map +1 -1
  55. package/dist/livestream-store/stream-key.js +2 -0
  56. package/dist/livestream-store/stream-key.js.map +1 -1
  57. package/dist/livestream-store/websocket-consumer.d.ts.map +1 -1
  58. package/dist/livestream-store/websocket-consumer.js +48 -0
  59. package/dist/livestream-store/websocket-consumer.js.map +1 -1
  60. package/dist/streamplace-provider/index.d.ts +3 -0
  61. package/dist/streamplace-provider/index.d.ts.map +1 -1
  62. package/dist/streamplace-provider/index.js +12 -1
  63. package/dist/streamplace-provider/index.js.map +1 -1
  64. package/dist/streamplace-store/block.d.ts +36 -2
  65. package/dist/streamplace-store/block.d.ts.map +1 -1
  66. package/dist/streamplace-store/block.js +121 -18
  67. package/dist/streamplace-store/block.js.map +1 -1
  68. package/dist/streamplace-store/branding.d.ts +27 -0
  69. package/dist/streamplace-store/branding.d.ts.map +1 -0
  70. package/dist/streamplace-store/branding.js +195 -0
  71. package/dist/streamplace-store/branding.js.map +1 -0
  72. package/dist/streamplace-store/index.d.ts +4 -0
  73. package/dist/streamplace-store/index.d.ts.map +1 -1
  74. package/dist/streamplace-store/index.js +4 -0
  75. package/dist/streamplace-store/index.js.map +1 -1
  76. package/dist/streamplace-store/moderation.d.ts +16 -0
  77. package/dist/streamplace-store/moderation.d.ts.map +1 -0
  78. package/dist/streamplace-store/moderation.js +141 -0
  79. package/dist/streamplace-store/moderation.js.map +1 -0
  80. package/dist/streamplace-store/moderator-management.d.ts +44 -0
  81. package/dist/streamplace-store/moderator-management.d.ts.map +1 -0
  82. package/dist/streamplace-store/moderator-management.js +136 -0
  83. package/dist/streamplace-store/moderator-management.js.map +1 -0
  84. package/dist/streamplace-store/streamplace-store.d.ts +6 -0
  85. package/dist/streamplace-store/streamplace-store.d.ts.map +1 -1
  86. package/dist/streamplace-store/streamplace-store.js +6 -0
  87. package/dist/streamplace-store/streamplace-store.js.map +1 -1
  88. package/dist/streamplace-store/xrpc.d.ts +1 -0
  89. package/dist/streamplace-store/xrpc.d.ts.map +1 -1
  90. package/dist/streamplace-store/xrpc.js +16 -0
  91. package/dist/streamplace-store/xrpc.js.map +1 -1
  92. package/locales/en-US/settings.ftl +91 -0
  93. package/node-compile-cache/v22.15.0-x64-efe9a9df-0/37be0eec +0 -0
  94. package/package.json +3 -3
  95. package/src/components/chat/chat-box.tsx +3 -1
  96. package/src/components/chat/mod-view.tsx +431 -121
  97. package/src/components/dashboard/chat-panel.tsx +2 -1
  98. package/src/components/dashboard/index.tsx +1 -0
  99. package/src/components/dashboard/moderator-panel.tsx +632 -0
  100. package/src/components/ui/menu.tsx +1 -2
  101. package/src/crypto-polyfill.native.tsx +8 -1
  102. package/src/hooks/index.ts +1 -0
  103. package/src/hooks/useDocumentTitle.tsx +45 -0
  104. package/src/lib/theme/branded-theme-provider.tsx +58 -0
  105. package/src/lib/theme/index.ts +3 -0
  106. package/src/livestream-store/chat.tsx +0 -2
  107. package/src/livestream-store/livestream-state.tsx +5 -0
  108. package/src/livestream-store/livestream-store.tsx +2 -0
  109. package/src/livestream-store/stream-key.tsx +3 -0
  110. package/src/livestream-store/websocket-consumer.tsx +60 -0
  111. package/src/streamplace-provider/index.tsx +23 -4
  112. package/src/streamplace-store/block.tsx +139 -19
  113. package/src/streamplace-store/branding.tsx +216 -0
  114. package/src/streamplace-store/index.tsx +4 -0
  115. package/src/streamplace-store/moderation.tsx +185 -0
  116. package/src/streamplace-store/moderator-management.tsx +175 -0
  117. package/src/streamplace-store/streamplace-store.tsx +15 -0
  118. package/src/streamplace-store/xrpc.tsx +18 -1
  119. package/dist/assets/emoji-data.json +0 -19371
  120. package/src/assets/emoji-data.json +0 -19371
@@ -2,12 +2,23 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useCreateBlockRecord = useCreateBlockRecord;
4
4
  exports.useCreateHideChatRecord = useCreateHideChatRecord;
5
+ exports.useUpdateLivestreamRecord = useUpdateLivestreamRecord;
5
6
  const react_1 = require("react");
6
7
  const xrpc_1 = require("./xrpc");
8
+ /**
9
+ * Hook to create a block record (ban user from chat).
10
+ *
11
+ * When the caller is the stream owner (agent.did === streamerDID), creates the
12
+ * block record directly via ATProto writes to their repo.
13
+ *
14
+ * When the caller is a delegated moderator, uses the place.stream.moderation.createBlock
15
+ * XRPC endpoint which validates permissions and creates the record using the
16
+ * streamer's OAuth session.
17
+ */
7
18
  function useCreateBlockRecord() {
8
19
  let agent = (0, xrpc_1.usePDSAgent)();
9
20
  const [isLoading, setIsLoading] = (0, react_1.useState)(false);
10
- const createBlock = async (subjectDID) => {
21
+ const createBlock = async (subjectDID, streamerDID) => {
11
22
  if (!agent) {
12
23
  throw new Error("No PDS agent found");
13
24
  }
@@ -16,15 +27,24 @@ function useCreateBlockRecord() {
16
27
  }
17
28
  setIsLoading(true);
18
29
  try {
19
- const record = {
20
- $type: "app.bsky.graph.block",
30
+ // If no streamerDID provided or caller is the streamer, use direct ATProto write
31
+ if (!streamerDID || agent.did === streamerDID) {
32
+ const record = {
33
+ $type: "app.bsky.graph.block",
34
+ subject: subjectDID,
35
+ createdAt: new Date().toISOString(),
36
+ };
37
+ const result = await agent.com.atproto.repo.createRecord({
38
+ repo: agent.did,
39
+ collection: "app.bsky.graph.block",
40
+ record,
41
+ });
42
+ return result;
43
+ }
44
+ // Otherwise, use delegated moderation endpoint
45
+ const result = await agent.place.stream.moderation.createBlock({
46
+ streamer: streamerDID,
21
47
  subject: subjectDID,
22
- createdAt: new Date().toISOString(),
23
- };
24
- const result = await agent.com.atproto.repo.createRecord({
25
- repo: agent.did,
26
- collection: "app.bsky.graph.block",
27
- record,
28
48
  });
29
49
  return result;
30
50
  }
@@ -34,10 +54,20 @@ function useCreateBlockRecord() {
34
54
  };
35
55
  return { createBlock, isLoading };
36
56
  }
57
+ /**
58
+ * Hook to create a gate record (hide a chat message).
59
+ *
60
+ * When the caller is the stream owner (agent.did === streamerDID), creates the
61
+ * gate record directly via ATProto writes to their repo.
62
+ *
63
+ * When the caller is a delegated moderator, uses the place.stream.moderation.createGate
64
+ * XRPC endpoint which validates permissions and creates the record using the
65
+ * streamer's OAuth session.
66
+ */
37
67
  function useCreateHideChatRecord() {
38
68
  let agent = (0, xrpc_1.usePDSAgent)();
39
69
  const [isLoading, setIsLoading] = (0, react_1.useState)(false);
40
- const createHideChat = async (chatMessageUri) => {
70
+ const createHideChat = async (chatMessageUri, streamerDID) => {
41
71
  if (!agent) {
42
72
  throw new Error("No PDS agent found");
43
73
  }
@@ -46,14 +76,23 @@ function useCreateHideChatRecord() {
46
76
  }
47
77
  setIsLoading(true);
48
78
  try {
49
- const record = {
50
- $type: "place.stream.chat.gate",
51
- hiddenMessage: chatMessageUri,
52
- };
53
- const result = await agent.com.atproto.repo.createRecord({
54
- repo: agent.did,
55
- collection: "place.stream.chat.gate",
56
- record,
79
+ // If no streamerDID provided or caller is the streamer, use direct ATProto write
80
+ if (!streamerDID || agent.did === streamerDID) {
81
+ const record = {
82
+ $type: "place.stream.chat.gate",
83
+ hiddenMessage: chatMessageUri,
84
+ };
85
+ const result = await agent.com.atproto.repo.createRecord({
86
+ repo: agent.did,
87
+ collection: "place.stream.chat.gate",
88
+ record,
89
+ });
90
+ return result;
91
+ }
92
+ // Otherwise, use delegated moderation endpoint
93
+ const result = await agent.place.stream.moderation.createGate({
94
+ streamer: streamerDID,
95
+ messageUri: chatMessageUri,
57
96
  });
58
97
  return result;
59
98
  }
@@ -63,4 +102,68 @@ function useCreateHideChatRecord() {
63
102
  };
64
103
  return { createHideChat, isLoading };
65
104
  }
105
+ /**
106
+ * Hook to update a livestream record (update stream title).
107
+ *
108
+ * When the caller is the stream owner (agent.did === streamerDID), updates the
109
+ * livestream record directly via ATProto writes to their repo.
110
+ *
111
+ * When the caller is a delegated moderator, uses the place.stream.moderation.updateLivestream
112
+ * XRPC endpoint which validates permissions and updates the record using the
113
+ * streamer's OAuth session.
114
+ */
115
+ function useUpdateLivestreamRecord() {
116
+ let agent = (0, xrpc_1.usePDSAgent)();
117
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
118
+ const updateLivestream = async (livestreamUri, title, streamerDID) => {
119
+ if (!agent) {
120
+ throw new Error("No PDS agent found");
121
+ }
122
+ if (!agent.did) {
123
+ throw new Error("No user DID found, assuming not logged in");
124
+ }
125
+ setIsLoading(true);
126
+ try {
127
+ // If no streamerDID provided or caller is the streamer, use direct ATProto write
128
+ if (!streamerDID || agent.did === streamerDID) {
129
+ // Extract rkey from URI
130
+ const rkey = livestreamUri.split("/").pop();
131
+ if (!rkey) {
132
+ throw new Error("Invalid livestream URI");
133
+ }
134
+ // Get existing record to copy fields
135
+ const getResult = await agent.com.atproto.repo.getRecord({
136
+ repo: agent.did,
137
+ collection: "place.stream.livestream",
138
+ rkey,
139
+ });
140
+ const oldRecord = getResult.data.value;
141
+ // Create new record (don't edit - old records are "chapter markers")
142
+ // Spread entire record to preserve all fields (agent, canonicalUrl, notificationSettings, etc.)
143
+ const record = {
144
+ ...oldRecord,
145
+ title: title, // Override title
146
+ createdAt: new Date().toISOString(), // Override timestamp for new chapter marker
147
+ };
148
+ const result = await agent.com.atproto.repo.createRecord({
149
+ repo: agent.did,
150
+ collection: "place.stream.livestream",
151
+ record,
152
+ });
153
+ return result;
154
+ }
155
+ // Otherwise, use delegated moderation endpoint
156
+ const result = await agent.place.stream.moderation.updateLivestream({
157
+ streamer: streamerDID,
158
+ livestreamUri: livestreamUri,
159
+ title: title,
160
+ });
161
+ return result;
162
+ }
163
+ finally {
164
+ setIsLoading(false);
165
+ }
166
+ };
167
+ return { updateLivestream, isLoading };
168
+ }
66
169
  //# sourceMappingURL=block.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"block.js","sourceRoot":"","sources":["../../src/streamplace-store/block.tsx"],"names":[],"mappings":";;AAIA,oDAgCC;AAED,0DAgCC;AArED,iCAAiC;AACjC,iCAAqC;AAErC,SAAgB,oBAAoB;IAClC,IAAI,KAAK,GAAG,IAAA,kBAAW,GAAE,CAAC;IAC1B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAElD,MAAM,WAAW,GAAG,KAAK,EAAE,UAAkB,EAAE,EAAE;QAC/C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,MAAM,GAA6B;gBACvC,KAAK,EAAE,sBAAsB;gBAC7B,OAAO,EAAE,UAAU;gBACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;aACpC,CAAC;YACF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;gBACvD,IAAI,EAAE,KAAK,CAAC,GAAG;gBACf,UAAU,EAAE,sBAAsB;gBAClC,MAAM;aACP,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;AACpC,CAAC;AAED,SAAgB,uBAAuB;IACrC,IAAI,KAAK,GAAG,IAAA,kBAAW,GAAE,CAAC;IAC1B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAElD,MAAM,cAAc,GAAG,KAAK,EAAE,cAAsB,EAAE,EAAE;QACtD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG;gBACb,KAAK,EAAE,wBAAwB;gBAC/B,aAAa,EAAE,cAAc;aAC9B,CAAC;YAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;gBACvD,IAAI,EAAE,KAAK,CAAC,GAAG;gBACf,UAAU,EAAE,wBAAwB;gBACpC,MAAM;aACP,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"block.js","sourceRoot":"","sources":["../../src/streamplace-store/block.tsx"],"names":[],"mappings":";;AAcA,oDA0CC;AAYD,0DA6CC;AAYD,8DAiEC;AA7LD,iCAAiC;AACjC,iCAAqC;AAErC;;;;;;;;;GASG;AACH,SAAgB,oBAAoB;IAClC,IAAI,KAAK,GAAG,IAAA,kBAAW,GAAE,CAAC;IAC1B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAElD,MAAM,WAAW,GAAG,KAAK,EAAE,UAAkB,EAAE,WAAoB,EAAE,EAAE;QACrE,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC;YACH,iFAAiF;YACjF,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;gBAC9C,MAAM,MAAM,GAA6B;oBACvC,KAAK,EAAE,sBAAsB;oBAC7B,OAAO,EAAE,UAAU;oBACnB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;iBACpC,CAAC;gBACF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;oBACvD,IAAI,EAAE,KAAK,CAAC,GAAG;oBACf,UAAU,EAAE,sBAAsB;oBAClC,MAAM;iBACP,CAAC,CAAC;gBACH,OAAO,MAAM,CAAC;YAChB,CAAC;YAED,+CAA+C;YAC/C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,WAAW,CAAC;gBAC7D,QAAQ,EAAE,WAAW;gBACrB,OAAO,EAAE,UAAU;aACpB,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;AACpC,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,uBAAuB;IACrC,IAAI,KAAK,GAAG,IAAA,kBAAW,GAAE,CAAC;IAC1B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAElD,MAAM,cAAc,GAAG,KAAK,EAC1B,cAAsB,EACtB,WAAoB,EACpB,EAAE;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC;YACH,iFAAiF;YACjF,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;gBAC9C,MAAM,MAAM,GAAG;oBACb,KAAK,EAAE,wBAAwB;oBAC/B,aAAa,EAAE,cAAc;iBAC9B,CAAC;gBAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;oBACvD,IAAI,EAAE,KAAK,CAAC,GAAG;oBACf,UAAU,EAAE,wBAAwB;oBACpC,MAAM;iBACP,CAAC,CAAC;gBACH,OAAO,MAAM,CAAC;YAChB,CAAC;YAED,+CAA+C;YAC/C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC;gBAC5D,QAAQ,EAAE,WAAW;gBACrB,UAAU,EAAE,cAAc;aAC3B,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC;AACvC,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,yBAAyB;IACvC,IAAI,KAAK,GAAG,IAAA,kBAAW,GAAE,CAAC;IAC1B,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAElD,MAAM,gBAAgB,GAAG,KAAK,EAC5B,aAAqB,EACrB,KAAa,EACb,WAAoB,EACpB,EAAE;QACF,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,YAAY,CAAC,IAAI,CAAC,CAAC;QACnB,IAAI,CAAC;YACH,iFAAiF;YACjF,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,KAAK,WAAW,EAAE,CAAC;gBAC9C,wBAAwB;gBACxB,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;gBAC5C,IAAI,CAAC,IAAI,EAAE,CAAC;oBACV,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;gBAC5C,CAAC;gBAED,qCAAqC;gBACrC,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;oBACvD,IAAI,EAAE,KAAK,CAAC,GAAG;oBACf,UAAU,EAAE,yBAAyB;oBACrC,IAAI;iBACL,CAAC,CAAC;gBAEH,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,KAAY,CAAC;gBAE9C,qEAAqE;gBACrE,gGAAgG;gBAChG,MAAM,MAAM,GAAG;oBACb,GAAG,SAAS;oBACZ,KAAK,EAAE,KAAK,EAAE,iBAAiB;oBAC/B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,4CAA4C;iBAClF,CAAC;gBAEF,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC;oBACvD,IAAI,EAAE,KAAK,CAAC,GAAG;oBACf,UAAU,EAAE,yBAAyB;oBACrC,MAAM;iBACP,CAAC,CAAC;gBACH,OAAO,MAAM,CAAC;YAChB,CAAC;YAED,+CAA+C;YAC/C,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC;gBAClE,QAAQ,EAAE,WAAW;gBACrB,aAAa,EAAE,aAAa;gBAC5B,KAAK,EAAE,KAAK;aACb,CAAC,CAAC;YACH,OAAO,MAAM,CAAC;QAChB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC;AACzC,CAAC"}
@@ -0,0 +1,27 @@
1
+ export interface BrandingAsset {
2
+ key: string;
3
+ mimeType: string;
4
+ url?: string;
5
+ data?: string;
6
+ width?: number;
7
+ height?: number;
8
+ }
9
+ export declare function useFetchBroadcasterDID(): () => Promise<void>;
10
+ export declare function useFetchBranding(): ({ force }?: {
11
+ force?: boolean | undefined;
12
+ }) => Promise<void>;
13
+ export declare function useBrandingAsset(key: string): BrandingAsset | undefined;
14
+ export declare function useMainLogo(): string | undefined;
15
+ export declare function useFavicon(): string | undefined;
16
+ export declare function useSiteTitle(): string;
17
+ export declare function useSiteDescription(): string;
18
+ export declare function usePrimaryColor(): string;
19
+ export declare function useAccentColor(): string;
20
+ export declare function useDefaultStreamer(): string | undefined;
21
+ export declare function useSidebarBackgroundImage(): BrandingAsset | undefined;
22
+ export declare function useLegalLinks(): {
23
+ text: string;
24
+ url: string;
25
+ }[];
26
+ export declare function useBrandingAutoFetch(): void;
27
+ //# sourceMappingURL=branding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.d.ts","sourceRoot":"","sources":["../../src/streamplace-store/branding.tsx"],"names":[],"mappings":"AAQA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAaD,wBAAgB,sBAAsB,wBAsBrC;AAGD,wBAAgB,gBAAgB;;oBAqF/B;AAGD,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAEvE;AAGD,wBAAgB,WAAW,IAAI,MAAM,GAAG,SAAS,CAGhD;AAGD,wBAAgB,UAAU,IAAI,MAAM,GAAG,SAAS,CAG/C;AAGD,wBAAgB,YAAY,IAAI,MAAM,CAGrC;AAGD,wBAAgB,kBAAkB,IAAI,MAAM,CAG3C;AAGD,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAGD,wBAAgB,cAAc,IAAI,MAAM,CAGvC;AAGD,wBAAgB,kBAAkB,IAAI,MAAM,GAAG,SAAS,CAGvD;AAGD,wBAAgB,yBAAyB,IAAI,aAAa,GAAG,SAAS,CAErE;AAGD,wBAAgB,aAAa,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,CAU/D;AAGD,wBAAgB,oBAAoB,SASnC"}
@@ -0,0 +1,195 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useFetchBroadcasterDID = useFetchBroadcasterDID;
4
+ exports.useFetchBranding = useFetchBranding;
5
+ exports.useBrandingAsset = useBrandingAsset;
6
+ exports.useMainLogo = useMainLogo;
7
+ exports.useFavicon = useFavicon;
8
+ exports.useSiteTitle = useSiteTitle;
9
+ exports.useSiteDescription = useSiteDescription;
10
+ exports.usePrimaryColor = usePrimaryColor;
11
+ exports.useAccentColor = useAccentColor;
12
+ exports.useDefaultStreamer = useDefaultStreamer;
13
+ exports.useSidebarBackgroundImage = useSidebarBackgroundImage;
14
+ exports.useLegalLinks = useLegalLinks;
15
+ exports.useBrandingAutoFetch = useBrandingAutoFetch;
16
+ const tslib_1 = require("tslib");
17
+ const react_1 = require("react");
18
+ const storage_1 = tslib_1.__importDefault(require("../storage"));
19
+ const streamplace_store_1 = require("./streamplace-store");
20
+ const xrpc_1 = require("./xrpc");
21
+ // helper to convert blob to base64
22
+ const blobToBase64 = (blob) => {
23
+ return new Promise((resolve, reject) => {
24
+ const reader = new FileReader();
25
+ reader.onloadend = () => resolve(reader.result);
26
+ reader.onerror = reject;
27
+ reader.readAsDataURL(blob);
28
+ });
29
+ };
30
+ // hook to fetch broadcaster DID (unauthenticated)
31
+ function useFetchBroadcasterDID() {
32
+ const streamplaceAgent = (0, xrpc_1.usePossiblyUnauthedPDSAgent)();
33
+ const store = (0, streamplace_store_1.getStreamplaceStoreFromContext)();
34
+ return (0, react_1.useCallback)(async () => {
35
+ try {
36
+ if (!streamplaceAgent) {
37
+ throw new Error("Streamplace agent not available");
38
+ }
39
+ const result = await streamplaceAgent.place.stream.broadcast.getBroadcaster();
40
+ store.setState({ broadcasterDID: result.data.broadcaster });
41
+ if (result.data.server) {
42
+ store.setState({ serverDID: result.data.server });
43
+ }
44
+ if (result.data.admins) {
45
+ store.setState({ adminDIDs: result.data.admins });
46
+ }
47
+ }
48
+ catch (err) {
49
+ console.error("Failed to fetch broadcaster DID:", err);
50
+ }
51
+ }, [streamplaceAgent, store]);
52
+ }
53
+ // hook to fetch branding data from the server
54
+ function useFetchBranding() {
55
+ const streamplaceAgent = (0, xrpc_1.usePossiblyUnauthedPDSAgent)();
56
+ const broadcasterDID = (0, streamplace_store_1.useStreamplaceStore)((state) => state.broadcasterDID);
57
+ const url = (0, streamplace_store_1.useStreamplaceStore)((state) => state.url);
58
+ const store = (0, streamplace_store_1.getStreamplaceStoreFromContext)();
59
+ return (0, react_1.useCallback)(async ({ force = true } = {}) => {
60
+ if (!broadcasterDID)
61
+ return;
62
+ try {
63
+ store.setState({ brandingLoading: true });
64
+ // check localStorage first
65
+ const cacheKey = `branding:${broadcasterDID}`;
66
+ const cached = await storage_1.default.getItem(cacheKey);
67
+ if (!force && cached) {
68
+ try {
69
+ const parsed = JSON.parse(cached);
70
+ // check if cache is less than 1 hour old
71
+ if (Date.now() - parsed.timestamp < 60 * 60 * 1000) {
72
+ store.setState({
73
+ branding: parsed.data,
74
+ brandingLoading: false,
75
+ brandingError: null,
76
+ });
77
+ return;
78
+ }
79
+ }
80
+ catch (e) {
81
+ // invalid cache, continue to fetch
82
+ console.warn("Invalid branding cache, refetching", e);
83
+ }
84
+ }
85
+ // fetch branding metadata from server
86
+ if (!streamplaceAgent) {
87
+ throw new Error("Streamplace agent not available");
88
+ }
89
+ const res = await streamplaceAgent.place.stream.branding.getBranding({
90
+ broadcaster: broadcasterDID,
91
+ });
92
+ const assets = res.data.assets;
93
+ // convert assets array to keyed object and fetch blob data
94
+ const brandingMap = {};
95
+ for (const asset of assets) {
96
+ brandingMap[asset.key] = { ...asset };
97
+ // if data is already inline (text assets), use it directly
98
+ if (asset.data) {
99
+ brandingMap[asset.key].data = asset.data;
100
+ }
101
+ else if (asset.url) {
102
+ // for images, construct full URL and fetch blob
103
+ const fullUrl = `${url}${asset.url}`;
104
+ const blobRes = await fetch(fullUrl);
105
+ const blob = await blobRes.blob();
106
+ brandingMap[asset.key].data = await blobToBase64(blob);
107
+ }
108
+ }
109
+ // cache in localStorage
110
+ storage_1.default.setItem(cacheKey, JSON.stringify({
111
+ timestamp: Date.now(),
112
+ data: brandingMap,
113
+ }));
114
+ store.setState({
115
+ branding: brandingMap,
116
+ brandingLoading: false,
117
+ brandingError: null,
118
+ });
119
+ }
120
+ catch (err) {
121
+ console.error("Failed to fetch branding:", err);
122
+ store.setState({
123
+ brandingLoading: false,
124
+ brandingError: err.message || "Failed to fetch branding",
125
+ });
126
+ }
127
+ }, [broadcasterDID, streamplaceAgent, url, store]);
128
+ }
129
+ // hook to get a specific branding asset by key
130
+ function useBrandingAsset(key) {
131
+ return (0, streamplace_store_1.useStreamplaceStore)((state) => state.branding?.[key]);
132
+ }
133
+ // convenience hook for main logo
134
+ function useMainLogo() {
135
+ const asset = useBrandingAsset("mainLogo");
136
+ return asset?.data;
137
+ }
138
+ // convenience hook for favicon
139
+ function useFavicon() {
140
+ const asset = useBrandingAsset("favicon");
141
+ return asset?.data;
142
+ }
143
+ // convenience hook for site title
144
+ function useSiteTitle() {
145
+ const asset = useBrandingAsset("siteTitle");
146
+ return asset?.data || "My Streamplace Station";
147
+ }
148
+ // convenience hook for site description
149
+ function useSiteDescription() {
150
+ const asset = useBrandingAsset("siteDescription");
151
+ return asset?.data || "Live streaming platform";
152
+ }
153
+ // convenience hook for primary color
154
+ function usePrimaryColor() {
155
+ const asset = useBrandingAsset("primaryColor");
156
+ return asset?.data || "#6366f1";
157
+ }
158
+ // convenience hook for accent color
159
+ function useAccentColor() {
160
+ const asset = useBrandingAsset("accentColor");
161
+ return asset?.data || "#8b5cf6";
162
+ }
163
+ // convenience hook for default streamer
164
+ function useDefaultStreamer() {
165
+ const asset = useBrandingAsset("defaultStreamer");
166
+ return asset?.data || undefined;
167
+ }
168
+ // convenience hook for sidebar background image
169
+ function useSidebarBackgroundImage() {
170
+ return useBrandingAsset("sidebarBackgroundImage");
171
+ }
172
+ // convenience hook for legal links
173
+ function useLegalLinks() {
174
+ const asset = useBrandingAsset("legalLinks");
175
+ if (!asset?.data) {
176
+ return [];
177
+ }
178
+ try {
179
+ return JSON.parse(asset.data);
180
+ }
181
+ catch {
182
+ return [];
183
+ }
184
+ }
185
+ // hook to auto-fetch branding when broadcaster changes
186
+ function useBrandingAutoFetch() {
187
+ const fetchBranding = useFetchBranding();
188
+ const broadcasterDID = (0, streamplace_store_1.useStreamplaceStore)((state) => state.broadcasterDID);
189
+ (0, react_1.useEffect)(() => {
190
+ if (broadcasterDID) {
191
+ fetchBranding();
192
+ }
193
+ }, [broadcasterDID, fetchBranding]);
194
+ }
195
+ //# sourceMappingURL=branding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branding.js","sourceRoot":"","sources":["../../src/streamplace-store/branding.tsx"],"names":[],"mappings":"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"}
@@ -1,3 +1,7 @@
1
+ export * from "./block";
2
+ export * from "./branding";
3
+ export * from "./moderation";
4
+ export * from "./moderator-management";
1
5
  export * from "./stream";
2
6
  export * from "./streamplace-store";
3
7
  export * from "./user";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/streamplace-store/index.tsx"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/streamplace-store/index.tsx"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,YAAY,CAAC;AAC3B,cAAc,cAAc,CAAC;AAC7B,cAAc,wBAAwB,CAAC;AACvC,cAAc,UAAU,CAAC;AACzB,cAAc,qBAAqB,CAAC;AACpC,cAAc,QAAQ,CAAC"}
@@ -1,6 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./block"), exports);
5
+ tslib_1.__exportStar(require("./branding"), exports);
6
+ tslib_1.__exportStar(require("./moderation"), exports);
7
+ tslib_1.__exportStar(require("./moderator-management"), exports);
4
8
  tslib_1.__exportStar(require("./stream"), exports);
5
9
  tslib_1.__exportStar(require("./streamplace-store"), exports);
6
10
  tslib_1.__exportStar(require("./user"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/streamplace-store/index.tsx"],"names":[],"mappings":";;;AAAA,mDAAyB;AACzB,8DAAoC;AACpC,iDAAuB"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/streamplace-store/index.tsx"],"names":[],"mappings":";;;AAAA,kDAAwB;AACxB,qDAA2B;AAC3B,uDAA6B;AAC7B,iEAAuC;AACvC,mDAAyB;AACzB,8DAAoC;AACpC,iDAAuB"}
@@ -0,0 +1,16 @@
1
+ export interface ModerationPermissions {
2
+ canBan: boolean;
3
+ canHide: boolean;
4
+ canManageLivestream: boolean;
5
+ isOwner: boolean;
6
+ isLoading: boolean;
7
+ error: string | null;
8
+ }
9
+ /**
10
+ * Hook to check if the current user can moderate for a given streamer.
11
+ * Returns permission flags based on:
12
+ * - Owner: full permissions if userDID === streamerDID
13
+ * - Delegated: permissions from place.stream.moderation.permission records
14
+ */
15
+ export declare function useCanModerate(streamerDID: string | null | undefined): ModerationPermissions;
16
+ //# sourceMappingURL=moderation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moderation.d.ts","sourceRoot":"","sources":["../../src/streamplace-store/moderation.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,mBAAmB,EAAE,OAAO,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GACrC,qBAAqB,CAkKvB"}
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useCanModerate = useCanModerate;
4
+ const react_1 = require("react");
5
+ const livestream_store_1 = require("../livestream-store/livestream-store");
6
+ const xrpc_1 = require("./xrpc");
7
+ /**
8
+ * Hook to check if the current user can moderate for a given streamer.
9
+ * Returns permission flags based on:
10
+ * - Owner: full permissions if userDID === streamerDID
11
+ * - Delegated: permissions from place.stream.moderation.permission records
12
+ */
13
+ function useCanModerate(streamerDID) {
14
+ const agent = (0, xrpc_1.usePDSAgent)();
15
+ const userDID = agent?.did;
16
+ // Get moderation permissions from livestream store (updated via WebSocket)
17
+ const moderationPermissions = (0, livestream_store_1.useLivestreamStore)((state) => state.moderationPermissions);
18
+ const setModerationPermissions = (0, livestream_store_1.useLivestreamStore)((state) => state.setModerationPermissions);
19
+ const [isOwner, setIsOwner] = (0, react_1.useState)(false);
20
+ const [isLoading, setIsLoading] = (0, react_1.useState)(false);
21
+ const [error, setError] = (0, react_1.useState)(null);
22
+ (0, react_1.useEffect)(() => {
23
+ if (!userDID || !streamerDID) {
24
+ setModerationPermissions([]);
25
+ setIsOwner(false);
26
+ setError(null);
27
+ return;
28
+ }
29
+ // If user is the streamer, they have full permissions
30
+ if (userDID === streamerDID) {
31
+ setIsOwner(true);
32
+ setModerationPermissions([]); // Not needed for owner
33
+ setIsLoading(false);
34
+ setError(null);
35
+ return;
36
+ }
37
+ // Otherwise, fetch delegation records from the streamer's repo
38
+ // This initial fetch populates the store, then WebSocket updates will keep it in sync
39
+ const fetchDelegation = async () => {
40
+ if (!agent) {
41
+ setModerationPermissions([]);
42
+ setIsLoading(false);
43
+ return;
44
+ }
45
+ setIsLoading(true);
46
+ setError(null);
47
+ setIsOwner(false);
48
+ try {
49
+ // Use authenticated agent to list permission records from the streamer's repo
50
+ const result = await agent.com.atproto.repo.listRecords({
51
+ repo: streamerDID,
52
+ collection: "place.stream.moderation.permission",
53
+ limit: 100,
54
+ });
55
+ const records = result.data.records || [];
56
+ const permissionRecords = records
57
+ .map((r) => r.value)
58
+ .filter((v) => v && v.$type === "place.stream.moderation.permission");
59
+ // Store all permissions in the livestream store
60
+ // WebSocket updates will keep this in sync
61
+ setModerationPermissions(permissionRecords);
62
+ }
63
+ catch (err) {
64
+ console.error("[useCanModerate] Error fetching permissions:", err);
65
+ setError(`Could not fetch moderation permissions: ${err instanceof Error ? err.message : `Unknown error: ${err}`}`);
66
+ setModerationPermissions([]);
67
+ }
68
+ finally {
69
+ setIsLoading(false);
70
+ }
71
+ };
72
+ // Fetch immediately on mount or when dependencies change
73
+ fetchDelegation();
74
+ }, [userDID, streamerDID, agent, setModerationPermissions]);
75
+ // If permissions were cleared (e.g., due to deletion), trigger a refetch
76
+ (0, react_1.useEffect)(() => {
77
+ // If permissions were cleared and we're not the owner, refetch
78
+ if (moderationPermissions.length === 0 &&
79
+ !isOwner &&
80
+ userDID &&
81
+ streamerDID &&
82
+ agent) {
83
+ const fetchDelegation = async () => {
84
+ try {
85
+ const result = await agent.com.atproto.repo.listRecords({
86
+ repo: streamerDID,
87
+ collection: "place.stream.moderation.permission",
88
+ limit: 100,
89
+ });
90
+ const records = result.data.records || [];
91
+ const permissionRecords = records
92
+ .map((r) => r.value)
93
+ .filter((v) => v && v.$type === "place.stream.moderation.permission");
94
+ setModerationPermissions(permissionRecords);
95
+ }
96
+ catch (err) {
97
+ console.error("[useCanModerate] Error refetching permissions:", err);
98
+ }
99
+ };
100
+ // Small delay to avoid rapid refetches
101
+ const timeout = setTimeout(fetchDelegation, 100);
102
+ return () => clearTimeout(timeout);
103
+ }
104
+ }, [
105
+ moderationPermissions.length,
106
+ isOwner,
107
+ userDID,
108
+ streamerDID,
109
+ agent,
110
+ setModerationPermissions,
111
+ ]);
112
+ // Find ALL delegation records for this moderator and merge their permissions
113
+ const delegations = moderationPermissions.filter((perm) => perm.moderator === userDID);
114
+ // Merge permissions from all delegation records for this moderator
115
+ const permissions = delegations.reduce((acc, delegation) => {
116
+ // Check if delegation has expired
117
+ if (delegation.expirationTime) {
118
+ const expiration = new Date(delegation.expirationTime);
119
+ if (new Date() > expiration) {
120
+ return acc; // Skip expired delegations
121
+ }
122
+ }
123
+ // Add all permissions from this delegation, avoiding duplicates
124
+ const delegationPerms = delegation.permissions || [];
125
+ for (const perm of delegationPerms) {
126
+ if (!acc.includes(perm)) {
127
+ acc.push(perm);
128
+ }
129
+ }
130
+ return acc;
131
+ }, []);
132
+ return {
133
+ canBan: isOwner || permissions.includes("ban"),
134
+ canHide: isOwner || permissions.includes("hide"),
135
+ canManageLivestream: isOwner || permissions.includes("livestream.manage"),
136
+ isOwner,
137
+ isLoading,
138
+ error,
139
+ };
140
+ }
141
+ //# sourceMappingURL=moderation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"moderation.js","sourceRoot":"","sources":["../../src/streamplace-store/moderation.tsx"],"names":[],"mappings":";;AAoBA,wCAoKC;AAxLD,iCAA4C;AAE5C,2EAA0E;AAC1E,iCAAqC;AAWrC;;;;;GAKG;AACH,SAAgB,cAAc,CAC5B,WAAsC;IAEtC,MAAM,KAAK,GAAG,IAAA,kBAAW,GAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,KAAK,EAAE,GAAG,CAAC;IAE3B,2EAA2E;IAC3E,MAAM,qBAAqB,GAAG,IAAA,qCAAkB,EAC9C,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,qBAAqB,CACvC,CAAC;IACF,MAAM,wBAAwB,GAAG,IAAA,qCAAkB,EACjD,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,wBAAwB,CAC1C,CAAC;IAEF,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,IAAA,gBAAQ,EAAC,KAAK,CAAC,CAAC;IAClD,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAgB,IAAI,CAAC,CAAC;IAExD,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,CAAC,OAAO,IAAI,CAAC,WAAW,EAAE,CAAC;YAC7B,wBAAwB,CAAC,EAAE,CAAC,CAAC;YAC7B,UAAU,CAAC,KAAK,CAAC,CAAC;YAClB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QAED,sDAAsD;QACtD,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;YAC5B,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,wBAAwB,CAAC,EAAE,CAAC,CAAC,CAAC,uBAAuB;YACrD,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,OAAO;QACT,CAAC;QAED,+DAA+D;QAC/D,sFAAsF;QACtF,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;YACjC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,wBAAwB,CAAC,EAAE,CAAC,CAAC;gBAC7B,YAAY,CAAC,KAAK,CAAC,CAAC;gBACpB,OAAO;YACT,CAAC;YAED,YAAY,CAAC,IAAI,CAAC,CAAC;YACnB,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,UAAU,CAAC,KAAK,CAAC,CAAC;YAElB,IAAI,CAAC;gBACH,8EAA8E;gBAC9E,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;oBACtD,IAAI,EAAE,WAAW;oBACjB,UAAU,EAAE,oCAAoC;oBAChD,KAAK,EAAE,GAAG;iBACX,CAAC,CAAC;gBAEH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;gBAC1C,MAAM,iBAAiB,GACrB,OAAO;qBACJ,GAAG,CAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;qBACnC,MAAM,CACL,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,oCAAoC,CAClE,CAAC;gBAEN,gDAAgD;gBAChD,2CAA2C;gBAC3C,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;YAC9C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,8CAA8C,EAAE,GAAG,CAAC,CAAC;gBACnE,QAAQ,CACN,2CAA2C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,kBAAkB,GAAG,EAAE,EAAE,CAC1G,CAAC;gBACF,wBAAwB,CAAC,EAAE,CAAC,CAAC;YAC/B,CAAC;oBAAS,CAAC;gBACT,YAAY,CAAC,KAAK,CAAC,CAAC;YACtB,CAAC;QACH,CAAC,CAAC;QAEF,yDAAyD;QACzD,eAAe,EAAE,CAAC;IACpB,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,wBAAwB,CAAC,CAAC,CAAC;IAE5D,yEAAyE;IACzE,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,+DAA+D;QAC/D,IACE,qBAAqB,CAAC,MAAM,KAAK,CAAC;YAClC,CAAC,OAAO;YACR,OAAO;YACP,WAAW;YACX,KAAK,EACL,CAAC;YACD,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;gBACjC,IAAI,CAAC;oBACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC;wBACtD,IAAI,EAAE,WAAW;wBACjB,UAAU,EAAE,oCAAoC;wBAChD,KAAK,EAAE,GAAG;qBACX,CAAC,CAAC;oBAEH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,IAAI,EAAE,CAAC;oBAC1C,MAAM,iBAAiB,GACrB,OAAO;yBACJ,GAAG,CAAC,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;yBACnC,MAAM,CACL,CAAC,CAAM,EAAE,EAAE,CACT,CAAC,IAAI,CAAC,CAAC,KAAK,KAAK,oCAAoC,CACxD,CAAC;oBAEN,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;gBAC9C,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,GAAG,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC,CAAC;YAEF,uCAAuC;YACvC,MAAM,OAAO,GAAG,UAAU,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;YACjD,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACrC,CAAC;IACH,CAAC,EAAE;QACD,qBAAqB,CAAC,MAAM;QAC5B,OAAO;QACP,OAAO;QACP,WAAW;QACX,KAAK;QACL,wBAAwB;KACzB,CAAC,CAAC;IAEH,6EAA6E;IAC7E,MAAM,WAAW,GAAG,qBAAqB,CAAC,MAAM,CAC9C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,KAAK,OAAO,CACrC,CAAC;IAEF,mEAAmE;IACnE,MAAM,WAAW,GAAa,WAAW,CAAC,MAAM,CAC9C,CAAC,GAAa,EAAE,UAAU,EAAE,EAAE;QAC5B,kCAAkC;QAClC,IAAI,UAAU,CAAC,cAAc,EAAE,CAAC;YAC9B,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;YACvD,IAAI,IAAI,IAAI,EAAE,GAAG,UAAU,EAAE,CAAC;gBAC5B,OAAO,GAAG,CAAC,CAAC,2BAA2B;YACzC,CAAC;QACH,CAAC;QAED,gEAAgE;QAChE,MAAM,eAAe,GAAG,UAAU,CAAC,WAAW,IAAI,EAAE,CAAC;QACrD,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;YACnC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjB,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,EACD,EAAE,CACH,CAAC;IAEF,OAAO;QACL,MAAM,EAAE,OAAO,IAAI,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;QAC9C,OAAO,EAAE,OAAO,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC;QAChD,mBAAmB,EAAE,OAAO,IAAI,WAAW,CAAC,QAAQ,CAAC,mBAAmB,CAAC;QACzE,OAAO;QACP,SAAS;QACT,KAAK;KACN,CAAC;AACJ,CAAC"}