kasunk99-livestream-core 0.3.11 → 0.3.13
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LiveStreamViewerItem.d.ts","sourceRoot":"","sources":["../../src/components/LiveStreamViewerItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqD,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"LiveStreamViewerItem.d.ts","sourceRoot":"","sources":["../../src/components/LiveStreamViewerItem.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAqD,MAAM,OAAO,CAAC;AAwB1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAO/C,KAAK,yBAAyB,GAAG;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AA8BF;;GAEG;AACH,eAAO,MAAM,oBAAoB,uDAiX/B,CAAC"}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { memo, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
-
import { ActivityIndicator,
|
|
3
|
+
import { ActivityIndicator, Dimensions, KeyboardAvoidingView, NativeModules, Platform, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View, } from 'react-native';
|
|
4
|
+
// react-native-keyboard-controller handles Android/iOS keyboard edge cases better
|
|
5
|
+
// than the built-in KeyboardAvoidingView. Fall back to the built-in if unavailable.
|
|
6
|
+
let KAV = KeyboardAvoidingView;
|
|
7
|
+
try {
|
|
8
|
+
KAV = require('react-native-keyboard-controller').KeyboardAvoidingView;
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
// use built-in
|
|
12
|
+
}
|
|
4
13
|
import { useViewerSocket } from '../hooks/useViewerSocket';
|
|
5
14
|
const SCREEN_HEIGHT = Dimensions.get('window').height;
|
|
6
15
|
const CHAT_NAME_COLORS = ['#f97316', '#22c55e', '#3b82f6', '#eab308', '#ec4899', '#a855f7'];
|
|
@@ -44,27 +53,6 @@ export const LiveStreamViewerItem = memo(function LiveStreamViewerItem({ stream,
|
|
|
44
53
|
const showVideo = RTCViewComponent && remoteStream && !!streamURL && hasVideoTrack;
|
|
45
54
|
const [chatInput, setChatInput] = useState('');
|
|
46
55
|
const [chatMessages, setChatMessages] = useState([]);
|
|
47
|
-
// iOS keyboard animation — Android handled automatically via windowSoftInputMode=adjustResize
|
|
48
|
-
const kbOffset = useRef(new Animated.Value(0)).current;
|
|
49
|
-
useEffect(() => {
|
|
50
|
-
if (Platform.OS !== 'ios')
|
|
51
|
-
return;
|
|
52
|
-
const show = Keyboard.addListener('keyboardWillShow', (e) => {
|
|
53
|
-
Animated.timing(kbOffset, {
|
|
54
|
-
toValue: e.endCoordinates.height,
|
|
55
|
-
duration: e.duration ?? 260,
|
|
56
|
-
useNativeDriver: false,
|
|
57
|
-
}).start();
|
|
58
|
-
});
|
|
59
|
-
const hide = Keyboard.addListener('keyboardWillHide', (e) => {
|
|
60
|
-
Animated.timing(kbOffset, {
|
|
61
|
-
toValue: 0,
|
|
62
|
-
duration: e.duration ?? 220,
|
|
63
|
-
useNativeDriver: false,
|
|
64
|
-
}).start();
|
|
65
|
-
});
|
|
66
|
-
return () => { show.remove(); hide.remove(); };
|
|
67
|
-
}, [kbOffset]);
|
|
68
56
|
const seededRoomRef = useRef(null);
|
|
69
57
|
const chatListRef = useRef(null);
|
|
70
58
|
const seededFromRoomState = useMemo(() => {
|
|
@@ -209,12 +197,12 @@ export const LiveStreamViewerItem = memo(function LiveStreamViewerItem({ stream,
|
|
|
209
197
|
};
|
|
210
198
|
const hostLabel = stream.hostDisplayName || stream.title || 'Live';
|
|
211
199
|
const avatarLetter = hostLabel[0]?.toUpperCase() ?? 'L';
|
|
212
|
-
return (_jsxs(
|
|
200
|
+
return (_jsxs(KAV, { style: styles.container, behavior: Platform.OS === 'ios' ? 'padding' : 'height', children: [showVideo && RTCViewComponent && streamURL ? (_jsx(RTCViewComponent, { streamURL: streamURL, stream: displayStream, style: styles.rtcView, objectFit: "cover", mirror: false }, `rtc-${trackCount}-${streamURL}`)) : (_jsxs(View, { style: styles.videoPlaceholder, children: [joining && (_jsx(ActivityIndicator, { size: "large", color: "rgba(255,255,255,0.6)" })), !joining && error && (_jsx(Text, { style: styles.placeholderError, children: error })), joined && !joining && !error && hasVideo && !remoteStream && (_jsx(ActivityIndicator, { size: "large", color: "rgba(255,255,255,0.45)" })), joined && !joining && !error && hasVideo && webrtcUnavailable && (_jsx(Text, { style: styles.placeholderHint, children: "Video needs a development build" })), joined && !joining && !error && hasVideo && consumeError && (_jsx(Text, { style: styles.placeholderError, children: consumeError }))] })), LinearGradient ? (_jsx(LinearGradient, { colors: [
|
|
213
201
|
'rgba(0,0,0,0.70)', // top edge — opaque for host info readability
|
|
214
202
|
'rgba(0,0,0,0.0)', // clears out ~30% down
|
|
215
203
|
'rgba(0,0,0,0.0)', // stays clear through mid-screen
|
|
216
204
|
'rgba(0,0,0,0.78)', // darkens toward bottom for chat / input
|
|
217
|
-
], locations: [0, 0.28, 0.48, 1], style: styles.gradientOverlay, pointerEvents: "none" })) : null, _jsxs(View, { style: styles.topBar, pointerEvents: "box-none", children: [_jsxs(View, { style: styles.hostRow, pointerEvents: "none", children: [_jsx(View, { style: styles.avatar, children: _jsx(Text, { style: styles.avatarLetter, children: avatarLetter }) }), _jsx(Text, { style: styles.hostName, numberOfLines: 1, children: hostLabel }), _jsx(View, { style: styles.livePill, children: _jsx(Text, { style: styles.livePillText, children: "LIVE" }) })] }), _jsxs(View, { style: styles.viewerChip, pointerEvents: "none", children: [_jsx(Text, { style: styles.viewerEye, children: "\uD83D\uDC41" }), _jsx(Text, { style: styles.viewerCount, children: viewerCount > 0 ? viewerCount.toLocaleString() : '—' })] })] }), _jsxs(View, { style: styles.rightColumn, pointerEvents: "box-none", children: [_jsxs(TouchableOpacity, { style: styles.actionBtn, activeOpacity: 0.75, children: [_jsx(View, { style: styles.actionCircle, children: _jsx(Text, { style: styles.actionIcon, children: "\u2665" }) }), _jsx(Text, { style: styles.actionLabel, children: "Like" })] }), _jsxs(TouchableOpacity, { style: styles.actionBtn, activeOpacity: 0.75, children: [_jsx(View, { style: styles.actionCircle, children: _jsx(Text, { style: styles.actionIcon, children: "\uD83C\uDF81" }) }), _jsx(Text, { style: styles.actionLabel, children: "Gift" })] }), _jsxs(TouchableOpacity, { style: styles.actionBtn, activeOpacity: 0.75, children: [_jsx(View, { style: styles.actionCircle, children: _jsx(Text, { style: styles.actionIcon, children: "\u2197" }) }), _jsx(Text, { style: styles.actionLabel, children: "Share" })] })] }), _jsxs(
|
|
205
|
+
], locations: [0, 0.28, 0.48, 1], style: styles.gradientOverlay, pointerEvents: "none" })) : null, _jsxs(View, { style: styles.topBar, pointerEvents: "box-none", children: [_jsxs(View, { style: styles.hostRow, pointerEvents: "none", children: [_jsx(View, { style: styles.avatar, children: _jsx(Text, { style: styles.avatarLetter, children: avatarLetter }) }), _jsx(Text, { style: styles.hostName, numberOfLines: 1, children: hostLabel }), _jsx(View, { style: styles.livePill, children: _jsx(Text, { style: styles.livePillText, children: "LIVE" }) })] }), _jsxs(View, { style: styles.viewerChip, pointerEvents: "none", children: [_jsx(Text, { style: styles.viewerEye, children: "\uD83D\uDC41" }), _jsx(Text, { style: styles.viewerCount, children: viewerCount > 0 ? viewerCount.toLocaleString() : '—' })] })] }), _jsxs(View, { style: styles.rightColumn, pointerEvents: "box-none", children: [_jsxs(TouchableOpacity, { style: styles.actionBtn, activeOpacity: 0.75, children: [_jsx(View, { style: styles.actionCircle, children: _jsx(Text, { style: styles.actionIcon, children: "\u2665" }) }), _jsx(Text, { style: styles.actionLabel, children: "Like" })] }), _jsxs(TouchableOpacity, { style: styles.actionBtn, activeOpacity: 0.75, children: [_jsx(View, { style: styles.actionCircle, children: _jsx(Text, { style: styles.actionIcon, children: "\uD83C\uDF81" }) }), _jsx(Text, { style: styles.actionLabel, children: "Gift" })] }), _jsxs(TouchableOpacity, { style: styles.actionBtn, activeOpacity: 0.75, children: [_jsx(View, { style: styles.actionCircle, children: _jsx(Text, { style: styles.actionIcon, children: "\u2197" }) }), _jsx(Text, { style: styles.actionLabel, children: "Share" })] })] }), _jsxs(View, { style: styles.bottomSection, pointerEvents: "box-none", children: [_jsx(View, { style: styles.chatColumn, pointerEvents: "box-none", children: _jsx(ScrollView, { ref: chatListRef, contentContainerStyle: styles.chatContent, showsVerticalScrollIndicator: false, keyboardShouldPersistTaps: "always", keyboardDismissMode: "none", children: chatData.map((item) => item.displayName ? (_jsx(View, { style: styles.chatBubble, children: _jsxs(Text, { style: styles.chatLine, numberOfLines: 3, children: [_jsxs(Text, { style: [styles.chatUsername, { color: getNameColor(item.displayName) }], children: [item.displayName, ' '] }), _jsx(Text, { style: styles.chatMsg, children: item.text })] }) }, item.id)) : (_jsx(View, { style: styles.joinBubble, children: _jsx(Text, { style: styles.joinText, children: item.text }) }, item.id))) }) }), _jsxs(View, { style: styles.inputBar, children: [_jsx(TouchableOpacity, { style: styles.inputIconBtn, activeOpacity: 0.7, children: _jsx(Text, { style: styles.inputIconGlyph, children: "\u263A" }) }), _jsx(TextInput, { style: styles.textInput, value: chatInput, onChangeText: setChatInput, placeholder: joined ? 'Say something...' : 'Connecting...', placeholderTextColor: "rgba(255,255,255,0.35)", editable: joined && !joining && !error, onSubmitEditing: sendChat, returnKeyType: "send", submitBehavior: "submit" }), _jsx(TouchableOpacity, { style: styles.inputIconBtn, activeOpacity: 0.7, children: _jsx(Text, { style: styles.inputIconGlyph, children: "\uD83C\uDF39" }) }), _jsx(TouchableOpacity, { style: [styles.sendBtn, (!chatInput.trim() || !joined) && styles.sendBtnOff], onPress: sendChat, activeOpacity: 0.75, disabled: !joined || !chatInput.trim(), children: _jsx(Text, { style: styles.sendIcon, children: "\u25B6" }) })] })] }), streamEnded && (_jsx(View, { style: styles.endedOverlay, children: _jsxs(View, { style: styles.endedCard, children: [_jsx(Text, { style: styles.endedTitle, children: "Stream ended" }), _jsx(Text, { style: styles.endedSub, children: "The host has ended this live stream" })] }) }))] }));
|
|
218
206
|
});
|
|
219
207
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
220
208
|
const styles = StyleSheet.create({
|
|
@@ -249,7 +237,7 @@ const styles = StyleSheet.create({
|
|
|
249
237
|
// ── Top bar ───────────────────────────────────────────────────────────────
|
|
250
238
|
topBar: {
|
|
251
239
|
position: 'absolute',
|
|
252
|
-
top:
|
|
240
|
+
top: 10,
|
|
253
241
|
left: 14,
|
|
254
242
|
right: 14,
|
|
255
243
|
flexDirection: 'row',
|
|
@@ -346,11 +334,10 @@ const styles = StyleSheet.create({
|
|
|
346
334
|
fontSize: 11,
|
|
347
335
|
fontWeight: '500',
|
|
348
336
|
},
|
|
349
|
-
// ── Bottom
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
right: 0,
|
|
337
|
+
// ── Bottom section (in-flow — KAV lifts this above the keyboard) ─────────
|
|
338
|
+
bottomSection: {
|
|
339
|
+
flex: 1,
|
|
340
|
+
justifyContent: 'flex-end',
|
|
354
341
|
paddingHorizontal: 12,
|
|
355
342
|
paddingBottom: BOTTOM_SAFE,
|
|
356
343
|
gap: 8,
|
package/package.json
CHANGED