Live video on the AT Protocol
1import {
2 DarkTheme,
3 LinkingOptions,
4 NavigationContainer,
5} from "@react-navigation/native";
6import * as Sentry from "@sentry/react-native";
7import {
8 BrandedThemeProvider,
9 I18nProvider,
10 StreamplaceProvider as ZustandStreamplaceProvider,
11} from "@streamplace/components";
12import { useFonts } from "expo-font";
13import BlueskyProvider from "features/bluesky/blueskyProvider";
14import StreamplaceProvider from "features/streamplace/streamplaceProvider";
15import useStreamplaceNode from "hooks/useStreamplaceNode";
16import React from "react";
17import { useOAuthSession } from "store/hooks";
18
19export default Sentry.wrap(ProviderInner);
20
21import { i18n } from "@streamplace/components";
22import * as Application from "expo-application";
23import Constants from "expo-constants";
24import * as Updates from "expo-updates";
25import { Platform } from "react-native";
26import { SafeAreaProvider } from "react-native-safe-area-context";
27Sentry.setExtras({
28 manifest: Updates.manifest,
29 linkingUri: Constants.linkingUri,
30});
31Sentry.setTag("expoChannel", Updates.channel);
32Sentry.setTag("appVersion", Application.nativeApplicationVersion);
33Sentry.setTag("deviceId", Constants.sessionId);
34Sentry.setTag("executionEnvironment", Constants.executionEnvironment);
35Sentry.setTag("expoGoVersion", Constants.expoVersion);
36Sentry.setTag("expoRuntimeVersion", Constants.expoRuntimeVersion);
37
38const isWeb = Platform.OS === "web";
39
40// set transparent dark theme on web for easier OBS browser sourcing
41const darkTheme = isWeb ? { background: "transparent" } : {};
42
43const SPDarkTheme = {
44 ...DarkTheme,
45 colors: {
46 ...DarkTheme.colors,
47 ...darkTheme,
48 },
49};
50
51function ProviderInner({
52 children,
53 linking,
54}: {
55 children: React.ReactNode;
56 linking: LinkingOptions<ReactNavigation.RootParamList>;
57}) {
58 // get proper DSN for environment
59 // on ios/android it's process.env.EXPO_PUBLIC_SENTRY_DSN
60 // on web it will be injected at runtime
61 let dsn = undefined;
62 if (Platform.OS === "web") {
63 dsn = (window as any).SENTRY_DSN;
64 } else {
65 dsn = process.env.EXPO_PUBLIC_SENTRY_DSN || undefined;
66 }
67
68 Sentry.init({
69 dsn,
70 // Adds more context data to events (IP address, cookies, user, etc.)
71 // For more information, visit: https://docs.sentry.io/platforms/react-native/data-management/data-collected/
72 sendDefaultPii: true,
73
74 // Configure Session Replay
75 replaysSessionSampleRate: 0.1,
76 replaysOnErrorSampleRate: 1,
77 integrations: [
78 Sentry.mobileReplayIntegration(),
79 Sentry.feedbackIntegration(),
80 ],
81
82 // uncomment the line below to enable Spotlight (https://spotlightjs.com)
83 spotlight: __DEV__,
84 });
85
86 return (
87 <SafeAreaProvider>
88 <I18nProvider i18n={i18n}>
89 <NavigationContainer theme={SPDarkTheme} linking={linking}>
90 <StreamplaceProvider>
91 <BlueskyProvider>
92 <NewStreamplaceProvider>
93 <BrandedThemeProvider forcedTheme="dark">
94 <FontProvider>{children}</FontProvider>
95 </BrandedThemeProvider>
96 </NewStreamplaceProvider>
97 </BlueskyProvider>
98 </StreamplaceProvider>
99 </NavigationContainer>
100 </I18nProvider>
101 </SafeAreaProvider>
102 );
103}
104
105export const NewStreamplaceProvider = ({
106 children,
107}: {
108 children: React.ReactNode;
109}) => {
110 const { url } = useStreamplaceNode();
111 const oauthSession = useOAuthSession();
112 return (
113 <ZustandStreamplaceProvider url={url} oauthSession={oauthSession}>
114 {children}
115 </ZustandStreamplaceProvider>
116 );
117};
118
119export const FontProvider = ({ children }: { children: React.ReactNode }) => {
120 const [fontLoaded, fontError] = useFonts({
121 // Atkinson Hyperlegible Next (Sans Serif) fonts
122 "AtkinsonHyperlegibleNext-Regular": require("../../assets/fonts/AtkinsonHyperlegibleNext-Regular.ttf"),
123 "AtkinsonHyperlegibleNext-Light": require("../../assets/fonts/AtkinsonHyperlegibleNext-Light.ttf"),
124 "AtkinsonHyperlegibleNext-ExtraLight": require("../../assets/fonts/AtkinsonHyperlegibleNext-ExtraLight.ttf"),
125 "AtkinsonHyperlegibleNext-Medium": require("../../assets/fonts/AtkinsonHyperlegibleNext-Medium.ttf"),
126 "AtkinsonHyperlegibleNext-SemiBold": require("../../assets/fonts/AtkinsonHyperlegibleNext-SemiBold.ttf"),
127 "AtkinsonHyperlegibleNext-Bold": require("../../assets/fonts/AtkinsonHyperlegibleNext-Bold.ttf"),
128 "AtkinsonHyperlegibleNext-ExtraBold": require("../../assets/fonts/AtkinsonHyperlegibleNext-ExtraBold.ttf"),
129
130 // Atkinson Hyperlegible Mono fonts
131 "AtkinsonHyperlegibleMono-Regular": require("../../assets/fonts/AtkinsonHyperlegibleMono-Regular.ttf"),
132 "AtkinsonHyperlegibleMono-Medium": require("../../assets/fonts/AtkinsonHyperlegibleMono-Medium.ttf"),
133 "AtkinsonHyperlegibleMono-SemiBold": require("../../assets/fonts/AtkinsonHyperlegibleMono-SemiBold.ttf"),
134 "AtkinsonHyperlegibleMono-Bold": require("../../assets/fonts/AtkinsonHyperlegibleMono-Bold.ttf"),
135 });
136
137 if (!fontLoaded && !fontError) {
138 return null;
139 }
140
141 return <>{children}</>;
142};