tangled
alpha
login
or
join now
stream.place
/
streamplace
Live video on the AT Protocol
74
fork
atom
overview
issues
1
pulls
pipelines
add 'current livestream problems' modal
Natalie B.
6 months ago
0ced2acc
35e2d821
+102
-24
1 changed file
expand all
collapse all
unified
split
js
app
src
screens
live-dashboard.tsx
+102
-24
js/app/src/screens/live-dashboard.tsx
···
2
2
LivestreamProvider,
3
3
useLivestreamStore,
4
4
} from "@streamplace/components";
5
5
-
import { Camera, FerrisWheel, X } from "@tamagui/lucide-icons";
5
5
+
import { LivestreamProblem } from "@streamplace/components/src/livestream-store/livestream-state";
6
6
+
import { Camera, ExternalLink, FerrisWheel, X } from "@tamagui/lucide-icons";
6
7
import { Redirect } from "components/aqlink";
7
8
import CreateLivestream from "components/create-livestream";
8
9
import UpdateLivestream from "components/edit-livestream";
···
22
23
} from "features/bluesky/blueskySlice";
23
24
import { useLiveUser } from "hooks/useLiveUser";
24
25
import React, { useCallback, useEffect, useState } from "react";
26
26
+
import { Linking, Pressable } from "react-native";
25
27
import { useAppDispatch, useAppSelector } from "store/hooks";
26
28
import { Button, H3, H6, isWeb, Text, View } from "tamagui";
27
29
···
123
125
{closeButton}
124
126
</View>
125
127
<View f={1} ai="center" jc="center" fb={0}>
126
126
-
<ButtonSelector
127
127
-
values={[
128
128
-
{ label: "Create", value: "create" },
129
129
-
{ label: "Update", value: "update" },
130
130
-
]}
131
131
-
disabledValues={isLive ? [] : ["update"]}
132
132
-
selectedValue={page}
133
133
-
setSelectedValue={setPage}
134
134
-
maxWidth={250}
135
135
-
width="100%"
136
136
-
/>
137
137
-
{page === "update" && isLive ? <UpdateLivestream /> : null}
138
138
-
{page === "create" ? <CreateLivestream /> : null}
139
139
-
</View>
140
140
-
<View>
141
141
-
<Problems />
128
128
+
<ProblemsWrapper>
129
129
+
<>
130
130
+
<ButtonSelector
131
131
+
values={[
132
132
+
{ label: "Create", value: "create" },
133
133
+
{ label: "Update", value: "update" },
134
134
+
]}
135
135
+
disabledValues={isLive ? [] : ["update"]}
136
136
+
selectedValue={page}
137
137
+
setSelectedValue={setPage}
138
138
+
maxWidth={250}
139
139
+
width="100%"
140
140
+
/>
141
141
+
{page === "update" && isLive ? <UpdateLivestream /> : null}
142
142
+
{page === "create" ? <CreateLivestream /> : null}
143
143
+
</>
144
144
+
</ProblemsWrapper>
142
145
</View>
143
146
{madeChoiceAboutDebugRecording ? null : <DebugRecordingPopup />}
144
147
</View>
···
147
150
);
148
151
}
149
152
150
150
-
const Problems = () => {
151
151
-
const problems = useLivestreamStore((x) => x.problems);
152
152
-
if (problems.length === 0) {
153
153
-
return null;
154
154
-
}
153
153
+
const Problems = ({
154
154
+
probs,
155
155
+
onIgnore,
156
156
+
}: {
157
157
+
probs: LivestreamProblem[];
158
158
+
onIgnore: () => void;
159
159
+
}) => {
155
160
return (
156
156
-
<View>
157
157
-
<Text>{JSON.stringify(problems, null, 2)}</Text>
161
161
+
<View gap={"$3"}>
162
162
+
<View>
163
163
+
<H3>Optimize Your Stream</H3>
164
164
+
<Text>
165
165
+
We’ve found a few things that could improve your stream’s reliability.
166
166
+
</Text>
167
167
+
</View>
168
168
+
{probs.map((p) => (
169
169
+
<View>
170
170
+
<View gap="$2" key={p.message} flexDirection="row" ai="flex-start">
171
171
+
<Text
172
172
+
borderRadius="$2"
173
173
+
px="$2"
174
174
+
bg={
175
175
+
p.severity === "error"
176
176
+
? "$red8Dark"
177
177
+
: p.severity === "warning"
178
178
+
? "$yellow8Dark"
179
179
+
: "$blue8Dark"
180
180
+
}
181
181
+
>
182
182
+
{p.severity}
183
183
+
</Text>
184
184
+
<View flex={1} gap="$1">
185
185
+
<Text>{p.code}</Text>
186
186
+
<Text color="$gray11Dark" fontSize="$6">
187
187
+
{p.message}
188
188
+
</Text>
189
189
+
{p.link && (
190
190
+
<Pressable onPress={() => p.link && Linking.openURL(p.link)}>
191
191
+
<View flexDirection="row" ai="center" gap="$2">
192
192
+
<Text color="$blue10" fontSize="$6">
193
193
+
Learn More
194
194
+
</Text>
195
195
+
<ExternalLink size="$1" />
196
196
+
</View>
197
197
+
</Pressable>
198
198
+
)}
199
199
+
</View>
200
200
+
</View>
201
201
+
</View>
202
202
+
))}
203
203
+
204
204
+
<Button onPress={onIgnore}>
205
205
+
<Text>Ignore</Text>
206
206
+
</Button>
158
207
</View>
208
208
+
);
209
209
+
};
210
210
+
211
211
+
const ProblemsWrapper = ({ children }: { children: React.ReactElement }) => {
212
212
+
const problems = useLivestreamStore((x) => x.problems);
213
213
+
const [dismiss, setDismiss] = useState(false);
214
214
+
215
215
+
return (
216
216
+
<>
217
217
+
{children}
218
218
+
{problems.length > 0 && !dismiss && (
219
219
+
<Popup
220
220
+
onClose={() => setDismiss(true)}
221
221
+
containerProps={{
222
222
+
top: "$4",
223
223
+
zIndex: 1000,
224
224
+
}}
225
225
+
bubbleProps={{
226
226
+
borderColor: "$gray5",
227
227
+
borderWidth: 1,
228
228
+
backgroundColor: "$gray1",
229
229
+
gap: "$3",
230
230
+
maxWidth: 400,
231
231
+
}}
232
232
+
>
233
233
+
<Problems probs={problems} onIgnore={() => setDismiss(true)} />
234
234
+
</Popup>
235
235
+
)}
236
236
+
</>
159
237
);
160
238
};
161
239