kasunk99-livestream-core 0.3.20 → 0.3.21
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;AAgB1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAM/C,KAAK,yBAAyB,GAAG;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAyCF,eAAO,MAAM,oBAAoB,uDAsZ/B,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
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, Keyboard, KeyboardAvoidingView, NativeModules, Platform, ScrollView,
|
|
3
|
+
import { ActivityIndicator, Keyboard, KeyboardAvoidingView as RNKeyboardAvoidingView, NativeModules, Platform, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View, } from 'react-native';
|
|
4
4
|
import { useViewerSocket } from '../hooks/useViewerSocket';
|
|
5
5
|
const CHAT_NAME_COLORS = ['#f97316', '#22c55e', '#3b82f6', '#eab308', '#ec4899', '#a855f7'];
|
|
6
6
|
const BOTTOM_SAFE = Platform.OS === 'ios' ? 28 : 10;
|
|
@@ -16,6 +16,16 @@ try {
|
|
|
16
16
|
LinearGradient = require('expo-linear-gradient').LinearGradient;
|
|
17
17
|
}
|
|
18
18
|
catch { }
|
|
19
|
+
// Use RNKC's KeyboardAvoidingView when available — it integrates with KeyboardProvider at the
|
|
20
|
+
// app root and uses WindowInsetsCompat + measure() for accurate positioning on Android.
|
|
21
|
+
// Falls back to React Native's built-in KAV for apps without RNKC installed.
|
|
22
|
+
let KeyboardAvoidingView = RNKeyboardAvoidingView;
|
|
23
|
+
try {
|
|
24
|
+
const rnkc = require('react-native-keyboard-controller');
|
|
25
|
+
if (rnkc.KeyboardAvoidingView)
|
|
26
|
+
KeyboardAvoidingView = rnkc.KeyboardAvoidingView;
|
|
27
|
+
}
|
|
28
|
+
catch { }
|
|
19
29
|
export const LiveStreamViewerItem = memo(function LiveStreamViewerItem({ stream, isActive, index: _index, }) {
|
|
20
30
|
const roomId = isActive ? stream.roomId : null;
|
|
21
31
|
const { joined, joining, error, producerList, roomState, remoteStream, remoteVideoStream, webrtcUnavailable, consumeError, socket, viewerCount: liveViewerCount, streamEnded, } = useViewerSocket(roomId);
|
|
@@ -52,33 +62,6 @@ export const LiveStreamViewerItem = memo(function LiveStreamViewerItem({ stream,
|
|
|
52
62
|
setIsTyping(false);
|
|
53
63
|
}
|
|
54
64
|
}, [isActive]);
|
|
55
|
-
// On Android, override adjustResize → adjustNothing while this stream is active.
|
|
56
|
-
//
|
|
57
|
-
// Why: the FlatList cell has a fixed height (set by LiveStreamFeed's viewportHeight state).
|
|
58
|
-
// With adjustResize the system shrinks the window, which eventually propagates to the cell,
|
|
59
|
-
// but by the time KeyboardAvoidingView fires the cell height has already changed — so KAV
|
|
60
|
-
// sees zero overlap with the keyboard and doesn't lift the content at all.
|
|
61
|
-
//
|
|
62
|
-
// With adjustNothing the window is untouched; KAV measures the exact overlap between its
|
|
63
|
-
// own screen rect and the keyboard rect, reduces its height by that amount, and the input
|
|
64
|
-
// bar ends up flush against the keyboard top with zero manual calculation.
|
|
65
|
-
//
|
|
66
|
-
// keyboardVerticalOffset corrects for the status bar: KAV's onLayout returns a y offset
|
|
67
|
-
// relative to its parent (= 0, top of the cell), but keyboardFrame.screenY is absolute
|
|
68
|
-
// screen coords. Without the offset KAV under-lifts by exactly StatusBar.currentHeight.
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
if (Platform.OS !== 'android' || !isActive)
|
|
71
|
-
return;
|
|
72
|
-
let cleanup;
|
|
73
|
-
try {
|
|
74
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
75
|
-
const rnkc = require('react-native-keyboard-controller');
|
|
76
|
-
rnkc.KeyboardController.setInputMode(rnkc.AndroidSoftInputModes.SOFT_INPUT_ADJUST_NOTHING);
|
|
77
|
-
cleanup = () => rnkc.KeyboardController.setDefaultMode();
|
|
78
|
-
}
|
|
79
|
-
catch { /* RNKC unavailable — falls back to adjustResize with partial lift */ }
|
|
80
|
-
return cleanup;
|
|
81
|
-
}, [isActive]);
|
|
82
65
|
const seededFromRoomState = useMemo(() => {
|
|
83
66
|
const chat = roomState && typeof roomState === 'object'
|
|
84
67
|
? roomState.chat
|
|
@@ -227,7 +210,7 @@ export const LiveStreamViewerItem = memo(function LiveStreamViewerItem({ stream,
|
|
|
227
210
|
// KeyboardAvoidingView is the root. It measures its own screen rect, computes the exact
|
|
228
211
|
// overlap with the system keyboard, and shrinks its content area accordingly.
|
|
229
212
|
// No manual offset formulas or layout listeners are needed.
|
|
230
|
-
_jsxs(KeyboardAvoidingView, { style: styles.container, behavior:
|
|
213
|
+
_jsxs(KeyboardAvoidingView, { style: styles.container, behavior: "padding", automaticOffset: true, children: [showVideo && RTCViewComponent && streamURL ? (_jsx(RTCViewComponent, { streamURL: streamURL, stream: displayStream, style: StyleSheet.absoluteFillObject, objectFit: "cover", mirror: false }, `rtc-${trackCount}-${streamURL}`)) : (_jsxs(View, { style: [StyleSheet.absoluteFillObject, 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: ['rgba(0,0,0,0.70)', 'rgba(0,0,0,0.0)', 'rgba(0,0,0,0.0)', 'rgba(0,0,0,0.78)'], locations: [0, 0.28, 0.48, 1], style: StyleSheet.absoluteFillObject, 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() : '—' })] })] }), !isTyping && (_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" })] })] })), _jsx(View, { style: styles.spacer, pointerEvents: "none" }), _jsx(ScrollView, { ref: chatListRef, style: styles.chatList, contentContainerStyle: styles.chatContent, showsVerticalScrollIndicator: false, keyboardShouldPersistTaps: "always", 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))) }), isTyping ? (
|
|
231
214
|
// Input bar — KAV lifts this to sit flush against the keyboard top.
|
|
232
215
|
_jsxs(View, { style: styles.inputBar, children: [_jsx(TextInput, { ref: textInputRef, style: styles.textInput, value: chatInput, onChangeText: setChatInput, placeholder: "Say something...", placeholderTextColor: "rgba(255,255,255,0.40)", editable: canType, onSubmitEditing: sendChat, returnKeyType: "send", submitBehavior: "submit", autoFocus: true }), _jsx(TouchableOpacity, { style: [styles.sendBtn, (!hasUnsent || !joined) && styles.sendBtnOff], onPress: sendChat, disabled: !joined || !hasUnsent, activeOpacity: 0.75, children: _jsx(Text, { style: styles.sendIcon, children: "\u25B6" }) })] })) : (
|
|
233
216
|
// Pill bar — tapping opens the input bar.
|
package/package.json
CHANGED