diff --git a/js/app/components/chat/chat-box.tsx b/js/app/components/chat/chat-box.tsx index 2a837986..3f79ac6e 100644 --- a/js/app/components/chat/chat-box.tsx +++ b/js/app/components/chat/chat-box.tsx @@ -1,15 +1,15 @@ +import { useNavigation } from "@react-navigation/native"; import { Send } from "@tamagui/lucide-icons"; -import { useRef, useState } from "react"; -import { Button, Form, isWeb, View, Input, TextArea } from "tamagui"; -import { Keyboard } from "react-native"; -import { usePlayerLivestream } from "features/player/playerSlice"; -import { useAppDispatch, useAppSelector } from "store/hooks"; import { chatPost, selectIsReady, selectUserProfile, } from "features/bluesky/blueskySlice"; -import { useNavigation } from "@react-navigation/native"; +import { usePlayerLivestream } from "features/player/playerSlice"; +import { useRef, useState } from "react"; +import { Keyboard } from "react-native"; +import { useAppDispatch, useAppSelector } from "store/hooks"; +import { Button, Form, Input, isWeb, TextArea, View } from "tamagui"; export default function ChatBox() { const [message, setMessage] = useState(""); @@ -79,6 +79,7 @@ export default function ChatBox() { submit(); } }} + onSubmitEditing={submit} /> - - - - )} - - - +

Player Telemetry

+ + Streamplace is beta software and it helps us out to have the + player report back on how playback is working. Would you like to + opt in to optional player telemetry? + + + + + + + )} -

{player.livestream?.record.title}

- - + + + +

{player.livestream?.record.title}

+ + + +
+
+ + + + + + {player.livestream?.record.title} + + + + + + + + + +
-
- - - - {player.livestream?.record.title} - - - - - - - - - - - - -
-
+ + + ); } diff --git a/js/app/components/player/provider.tsx b/js/app/components/player/provider.tsx index 5fdecabd..32b972ae 100644 --- a/js/app/components/player/provider.tsx +++ b/js/app/components/player/provider.tsx @@ -5,12 +5,11 @@ import { PlayerContext, usePlayerActions, } from "features/player/playerSlice"; -import { useState, useEffect, useContext, useRef } from "react"; +import { selectUrl } from "features/streamplace/streamplaceSlice"; +import { useContext, useEffect, useRef, useState } from "react"; +import useWebSocket, { ReadyState } from "react-use-websocket"; import { useAppDispatch, useAppSelector } from "store/hooks"; import { PlayerProps } from "./props"; -import { selectUrl } from "features/streamplace/streamplaceSlice"; -import useWebSocket from "react-use-websocket"; -import { ReadyState } from "react-use-websocket"; const POLL_INTERVAL = 3000; // PlayerInner starts doing player stuff @@ -76,7 +75,6 @@ export function PlayerDataContext( wsUrl = wsUrl.replace(/^https\:/, "wss:"); const ref = useRef([]); - const last = useRef(0); const handle = useRef(null); const { readyState } = useWebSocket(`${wsUrl}/api/websocket/${props.src}`, { @@ -84,10 +82,15 @@ export function PlayerDataContext( shouldReconnect: () => true, onOpen: () => { - console.log("onOpen"); ref.current = []; }, + onError: (e) => { + console.log("onError", e); + }, + + // spamming the redux store with messages causes a zillion re-renders, + // so we batch them up a bit onMessage: (msg) => { try { const data = JSON.parse(msg.data); @@ -95,18 +98,13 @@ export function PlayerDataContext( if (handle.current) { return; } - let scheduleUpdate = Date.now() - last.current; - if (scheduleUpdate < 0) { - scheduleUpdate = 0; - } handle.current = setTimeout(() => { dispatch(handleWebSocketMessages(ref.current)); ref.current = []; - last.current = Date.now(); handle.current = null; - }, scheduleUpdate); + }, 250); } catch (e) { - last.current = Date.now(); + console.log("onMessage parse error", e); } }, }); diff --git a/js/app/hooks/useKeyboard.tsx b/js/app/hooks/useKeyboard.tsx index f94c48ce..7fd41f7e 100644 --- a/js/app/hooks/useKeyboard.tsx +++ b/js/app/hooks/useKeyboard.tsx @@ -1,21 +1,41 @@ -import { useState, useEffect } from "react"; +import { useEffect, useState } from "react"; import { Keyboard } from "react-native"; export function useKeyboard() { const [isKeyboardVisible, setIsKeyboardVisible] = useState(false); - + const [keyboardHeight, setKeyboardHeight] = useState(0); useEffect(() => { - const showSubscription = Keyboard.addListener("keyboardDidShow", () => { + const willShowSubscription = Keyboard.addListener( + "keyboardWillShow", + (e) => { + // setIsKeyboardVisible(true); + setKeyboardHeight(e.endCoordinates.height); + console.log("keyboardWillShow", e.endCoordinates.height); + }, + ); + const willHideSubscription = Keyboard.addListener( + "keyboardWillHide", + (e) => { + // setIsKeyboardVisible(false); + setKeyboardHeight(0); + console.log("keyboardWillHide", e.endCoordinates.height); + }, + ); + const showSubscription = Keyboard.addListener("keyboardDidShow", (e) => { setIsKeyboardVisible(true); + setKeyboardHeight(e.endCoordinates.height); + console.log("keyboardDidShow", e.endCoordinates.height); }); const hideSubscription = Keyboard.addListener("keyboardDidHide", () => { setIsKeyboardVisible(false); + setKeyboardHeight(0); }); return () => { showSubscription.remove(); hideSubscription.remove(); + willShowSubscription.remove(); }; }, []); - return { isKeyboardVisible }; + return { isKeyboardVisible, keyboardHeight }; }