tangled
alpha
login
or
join now
stream.place
/
streamplace
Live video on the AT Protocol
74
fork
atom
overview
issues
1
pulls
pipelines
Merge branch 'natb/reporting-interface' into eli/reporting
Eli Mallon
6 months ago
edfc0806
b537ba11
+123
-2
5 changed files
expand all
collapse all
unified
split
js
app
components
mobile
desktop-ui.tsx
report-modal.tsx
components
src
components
ui
dialog.tsx
index.ts
primitives
modal.tsx
+10
js/app/components/mobile/desktop-ui.tsx
···
32
32
useSharedValue,
33
33
withTiming,
34
34
} from "react-native-reanimated";
35
35
+
import ReportModal from "./report-modal";
35
36
import { useResponsiveLayout } from "./useResponsiveLayout";
36
37
37
38
const { borders, colors, gap, h, layout, position, w, px, py, r, p, bg, text } =
···
189
190
const { doSetIngestCamera } = useCameraToggle();
190
191
const avatars = useAvatars(profile?.did ? [profile?.did] : []);
191
192
const { safeAreaInsets, shouldShowFloatingMetrics } = useResponsiveLayout();
193
193
+
194
194
+
const [reporting, setReporting] = useState(false);
192
195
193
196
const fullscreen = usePlayerStore((state) => state.fullscreen);
194
197
const setFullscreen = usePlayerStore((state) => state.setFullscreen);
···
454
457
onDone={() => {
455
458
setShowCountdown(false);
456
459
}}
460
460
+
/>
461
461
+
462
462
+
<ReportModal
463
463
+
open={reporting}
464
464
+
onOpenChange={setReporting}
465
465
+
title={`Report ${profile?.handle}`}
466
466
+
onSubmit={() => {}}
457
467
/>
458
468
459
469
<Toast
+111
js/app/components/mobile/report-modal.tsx
···
1
1
+
import {
2
2
+
Button,
3
3
+
Dialog,
4
4
+
DialogFooter,
5
5
+
ModalContent,
6
6
+
Text,
7
7
+
Textarea,
8
8
+
zero,
9
9
+
} from "@streamplace/components";
10
10
+
import { CheckCircle, Circle } from "@tamagui/lucide-icons";
11
11
+
import React, { useState } from "react";
12
12
+
import { TouchableOpacity, View } from "react-native";
13
13
+
14
14
+
const REPORT_REASONS = [
15
15
+
"Terrorism",
16
16
+
"Nudity or Sexually Explicit",
17
17
+
"Hateful Conduct",
18
18
+
"Bullying or Harassment",
19
19
+
"Violence or Gore",
20
20
+
"Self-Harm",
21
21
+
"Spam, Scams, Bots, or Tampering",
22
22
+
"Miscategorized Content",
23
23
+
"Missing or Incorrect Content Classification Label",
24
24
+
"Search",
25
25
+
];
26
26
+
27
27
+
interface ReportModalProps {
28
28
+
open: boolean;
29
29
+
onOpenChange: (open: boolean) => void;
30
30
+
onSubmit: (reason: string) => void;
31
31
+
title?: string;
32
32
+
description?: string;
33
33
+
}
34
34
+
35
35
+
export const ReportModal: React.FC<ReportModalProps> = ({
36
36
+
open,
37
37
+
onOpenChange,
38
38
+
onSubmit,
39
39
+
title = "Report",
40
40
+
description = "Why are you submitting this report?",
41
41
+
}) => {
42
42
+
const [selectedReason, setSelectedReason] = useState<string | null>(null);
43
43
+
44
44
+
const handleCancel = () => {
45
45
+
setSelectedReason(null);
46
46
+
onOpenChange(false);
47
47
+
};
48
48
+
49
49
+
const handleSubmit = () => {
50
50
+
if (selectedReason) {
51
51
+
onSubmit(selectedReason);
52
52
+
setSelectedReason(null);
53
53
+
onOpenChange(false);
54
54
+
}
55
55
+
};
56
56
+
57
57
+
return (
58
58
+
<Dialog
59
59
+
open={open}
60
60
+
onOpenChange={onOpenChange}
61
61
+
title={title}
62
62
+
description={description}
63
63
+
showCloseButton
64
64
+
variant="default"
65
65
+
size="md"
66
66
+
dismissible={false}
67
67
+
position="center"
68
68
+
>
69
69
+
<ModalContent style={[zero.pb[2]]}>
70
70
+
{REPORT_REASONS.map((reason) => (
71
71
+
<TouchableOpacity
72
72
+
key={reason}
73
73
+
onPress={() => setSelectedReason(reason)}
74
74
+
style={[
75
75
+
zero.layout.flex.row,
76
76
+
zero.gap.all[2],
77
77
+
zero.py[1],
78
78
+
zero.px[2],
79
79
+
zero.borderRadius[8],
80
80
+
zero.layout.flex.alignCenter,
81
81
+
]}
82
82
+
>
83
83
+
<View>
84
84
+
{selectedReason === reason ? <CheckCircle /> : <Circle />}
85
85
+
</View>
86
86
+
<Text>{reason}</Text>
87
87
+
</TouchableOpacity>
88
88
+
))}
89
89
+
90
90
+
<View style={[zero.pb[4], zero.mt[4], zero.px[2]]}>
91
91
+
<Text style={[zero.mb[2]]}>Additional Comments (optional)</Text>
92
92
+
<Textarea maxLength={500} numberOfLines={2} />
93
93
+
</View>
94
94
+
</ModalContent>
95
95
+
<DialogFooter>
96
96
+
<Button variant="secondary" onPress={handleCancel}>
97
97
+
<Text>Cancel</Text>
98
98
+
</Button>
99
99
+
<Button
100
100
+
variant="primary"
101
101
+
onPress={handleSubmit}
102
102
+
disabled={!selectedReason}
103
103
+
>
104
104
+
Submit
105
105
+
</Button>
106
106
+
</DialogFooter>
107
107
+
</Dialog>
108
108
+
);
109
109
+
};
110
110
+
111
111
+
export default ReportModal;
+1
-1
js/components/src/components/ui/dialog.tsx
···
254
254
255
255
// Dialog Close Icon component (Lucide X)
256
256
const DialogCloseIcon = () => {
257
257
-
return <ThemedX size="md" variant="muted" />;
257
257
+
return <ThemedX size="md" variant="default" />;
258
258
};
259
259
260
260
// Create theme-aware styles
+1
js/components/src/components/ui/index.ts
···
14
14
export * from "./resizeable";
15
15
export * from "./slider";
16
16
export * from "./text";
17
17
+
export * from "./textarea";
17
18
export * from "./toast";
18
19
export * from "./view";
19
20
-1
js/components/src/components/ui/primitives/modal.tsx
···
334
334
padding: 16,
335
335
},
336
336
content: {
337
337
-
backgroundColor: "white",
338
337
borderRadius: 8,
339
338
overflow: "hidden",
340
339
},