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