···11+import { theme } from "@streamplace/components";
22+import { Player } from "components/mobile/player";
33+import { FullscreenProvider } from "contexts/FullscreenContext";
44+import { selectUserProfile } from "features/bluesky/blueskySlice";
55+import { useAppSelector } from "store/hooks";
66+import { Text } from "tamagui";
77+88+export default function MobileGoLive() {
99+ const userProfile = useAppSelector(selectUserProfile);
1010+1111+ if (!userProfile) {
1212+ // If user profile is not available, redirect to login or show an error
1313+ return <Text>You need to log in to go live!</Text>;
1414+ }
1515+ // get player
1616+ return (
1717+ <theme.ThemeProvider>
1818+ <FullscreenProvider>
1919+ <Player ingest src={userProfile.did} name={userProfile.handle} />
2020+ </FullscreenProvider>
2121+ </theme.ThemeProvider>
2222+ );
2323+}
+30
js/app/src/screens/mobile-stream.tsx
···11+import { useNavigation } from "@react-navigation/native";
22+import { theme } from "@streamplace/components";
33+import { Player } from "components/mobile/player";
44+import { PlayerProps } from "components/player/props";
55+import { FullscreenProvider } from "contexts/FullscreenContext";
66+import { isWeb } from "tamagui";
77+import { queryToProps } from "./util";
88+99+export default function MobileStream({ route }) {
1010+ const { user, protocol, url } = route.params;
1111+ const navigation = useNavigation();
1212+ let extraProps: Partial<PlayerProps> = {};
1313+ if (isWeb) {
1414+ extraProps = queryToProps(new URLSearchParams(window.location.search));
1515+ }
1616+ let src = user;
1717+ if (user === "stream") {
1818+ src = url;
1919+ }
2020+2121+ console.log(src);
2222+2323+ return (
2424+ <theme.ThemeProvider>
2525+ <FullscreenProvider>
2626+ <Player src={src} {...extraProps} />
2727+ </FullscreenProvider>
2828+ </theme.ThemeProvider>
2929+ );
3030+}
···11+// Browser compatibility checks for WebRTC
22+const checkWebRTCSupport = () => {
33+ if (typeof window === "undefined") {
44+ throw new Error("WebRTC is not available in non-browser environments");
55+ }
66+77+ if (!window.RTCPeerConnection) {
88+ throw new Error(
99+ "RTCPeerConnection is not supported in this browser. Please use a modern browser that supports WebRTC.",
1010+ );
1111+ }
1212+1313+ if (!window.RTCSessionDescription) {
1414+ throw new Error(
1515+ "RTCSessionDescription is not supported in this browser. Please use a modern browser that supports WebRTC.",
1616+ );
1717+ }
1818+};
1919+2020+// Check support immediately
2121+try {
2222+ checkWebRTCSupport();
2323+} catch (error) {
2424+ console.error("WebRTC Compatibility Error:", error.message);
2525+}
2626+2727+export const RTCPeerConnection = window.RTCPeerConnection;
2828+export const RTCSessionDescription = window.RTCSessionDescription;
2929+export const WebRTCMediaStream = window.MediaStream;
3030+export const mediaDevices = navigator.mediaDevices;
3131+3232+// Export the compatibility checker for use in other components
3333+export { checkWebRTCSupport };
···11+import { type LucideProps } from "lucide-react-native";
22+import React from "react";
33+import { useTheme } from "../../lib/theme";
44+55+// Simple icon wrapper that integrates with theme
66+export interface IconProps {
77+ variant?:
88+ | "default"
99+ | "muted"
1010+ | "primary"
1111+ | "secondary"
1212+ | "destructive"
1313+ | "success"
1414+ | "warning";
1515+ size?: number | "sm" | "md" | "lg" | "xl";
1616+ color?: string;
1717+}
1818+1919+// Size mapping
2020+const sizeMap = {
2121+ sm: 16,
2222+ md: 20,
2323+ lg: 24,
2424+ xl: 32,
2525+} as const;
2626+2727+// HOC to create themed icons
2828+export function createThemedIcon(
2929+ IconComponent: React.ComponentType<LucideProps>,
3030+): React.FC<IconProps> {
3131+ return ({ variant = "default", size = "md", color, ...restProps }) => {
3232+ let theme = useTheme(); // Ensure theme is available
3333+ // Calculate size
3434+ const iconSize = typeof size === "number" ? size : sizeMap[size];
3535+3636+ // Calculate color if not provided using atoms
3737+ const iconColor =
3838+ color ||
3939+ theme.theme.colors[variant] ||
4040+ theme.theme.colors.secondaryForeground;
4141+4242+ return (
4343+ <IconComponent
4444+ size={iconSize}
4545+ color={iconColor}
4646+ {...(restProps as Omit<LucideProps, "size" | "color">)}
4747+ />
4848+ );
4949+ };
5050+}
+31
js/components/src/components/ui/index.ts
···11+// Export primitive components
22+export * from "./primitives/button";
33+export * from "./primitives/input";
44+export * from "./primitives/modal";
55+export * from "./primitives/text";
66+77+// Export styled components
88+export * from "./button";
99+export * from "./dialog";
1010+export * from "./dropdown";
1111+export * from "./icons";
1212+export * from "./input";
1313+export * from "./text";
1414+export * from "./toast";
1515+export * from "./view";
1616+1717+// Component collections for easy importing
1818+export { ButtonPrimitive } from "./primitives/button";
1919+export { InputPrimitive } from "./primitives/input";
2020+export { ModalPrimitive } from "./primitives/modal";
2121+export { TextPrimitive } from "./primitives/text";
2222+2323+// Re-export commonly used types
2424+export type { Theme } from "../../lib/theme/theme";
2525+export type { ButtonProps } from "./button";
2626+export type { DialogProps } from "./dialog";
2727+export type { InputProps } from "./input";
2828+export type { TextProps } from "./text";
2929+export type { ViewProps } from "./view";
3030+3131+export * from "../../lib/theme";
···44export * from "./player-store";
55export * from "./streamplace-provider";
66export * from "./streamplace-store";
77+88+// export PlayerProvider and related hooks/types for direct package imports
99+export {
1010+ PlayerProvider,
1111+ withPlayerProvider,
1212+} from "./player-store/player-provider";
1313+export { usePlayerContext } from "./player-store/player-store";
1414+1515+// export Player and PlayerProps for direct package imports
1616+export { Player, PlayerUI } from "./components/mobile-player/player";
1717+export { PlayerProps } from "./components/mobile-player/props";
1818+1919+// export theme
2020+export * as ui from "./components/ui";
2121+2222+// export all UI components at the root for direct imports
2323+export * from "./components/ui";
2424+2525+// export atoms and theme for direct imports
2626+export * as theme from "./lib/theme";
2727+export * as atoms from "./lib/theme/atoms";