Skip to content

Commit 148955e

Browse files
committed
Update example app runtime defaults
1 parent 44c1831 commit 148955e

5 files changed

Lines changed: 123 additions & 94 deletions

File tree

example/browser/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Exceptionless, prune } from "../../node_modules/@exceptionless/browser/dist/index.bundle.js";
2-
import "/node_modules/jquery/dist/jquery.js";
2+
import "../../node_modules/jquery/dist/jquery.js";
33

44
import { divide } from "./math.js";
55
import { TextAreaLogger } from "./text-area-logger.js";

example/expo/App.tsx

Lines changed: 104 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,28 @@
1-
import { createBottomTabNavigator } from "@react-navigation/bottom-tabs";
2-
import { NavigationContainer } from "@react-navigation/native";
31
import Constants from "expo-constants";
42
import * as Device from "expo-device";
5-
import { GlassView } from "expo-glass-effect";
63
import * as SplashScreen from "expo-splash-screen";
74
import { StatusBar } from "expo-status-bar";
85
import { useEffect, useMemo, useState } from "react";
9-
import { Platform, StyleSheet, Text, View } from "react-native";
6+
import { Platform, Pressable, StyleSheet, Text, View } from "react-native";
107
import { SafeAreaProvider, SafeAreaView } from "react-native-safe-area-context";
8+
import { Tabs, type TabSelectedEvent } from "react-native-screens";
119
import { Exceptionless } from "@exceptionless/react-native";
1210

1311
import { callbackLog, getLogEntries, subscribeToLogs } from "./logging";
1412
import ErrorsScreen from "./screens/ErrorsScreen";
1513
import EventsScreen from "./screens/EventsScreen";
1614
import LogsScreen from "./screens/LogsScreen";
1715

18-
type TabParamList = {
19-
Errors: undefined;
20-
Events: undefined;
21-
Logs: undefined;
22-
};
16+
type TabKey = "Errors" | "Events" | "Logs";
2317

24-
const Tab = createBottomTabNavigator<TabParamList>();
18+
const appTabs: Array<{ icon: string; key: TabKey; title: string }> = [
19+
{ icon: "exclamationmark.triangle", key: "Errors", title: "Errors" },
20+
{ icon: "tray.and.arrow.up", key: "Events", title: "Events" },
21+
{ icon: "list.bullet.rectangle", key: "Logs", title: "Logs" }
22+
];
2523

2624
const serverUrl = getServerUrl();
2725

28-
function TabIcon({ label, focused }: { label: string; focused: boolean }) {
29-
return <Text style={[styles.tabIcon, focused && styles.tabIconFocused]}>{label}</Text>;
30-
}
31-
3226
/**
3327
* Resolves the dev server URL based on the current platform.
3428
* - Web and iOS Simulator: localhost reaches the host Mac.
@@ -87,6 +81,67 @@ function TopDiagnostics() {
8781
);
8882
}
8983

84+
function NativeTabs() {
85+
const [selectedTab, setSelectedTab] = useState<TabKey>("Errors");
86+
const [baseProvenance, setBaseProvenance] = useState(0);
87+
const navStateRequest = useMemo(() => ({ baseProvenance, selectedScreenKey: selectedTab }), [baseProvenance, selectedTab]);
88+
89+
const handleTabSelected = (event: { nativeEvent: TabSelectedEvent }) => {
90+
setSelectedTab(event.nativeEvent.selectedScreenKey as TabKey);
91+
setBaseProvenance(event.nativeEvent.provenance);
92+
};
93+
94+
if (Platform.OS === "web") {
95+
const ActiveScreen = selectedTab === "Errors" ? ErrorsScreen : selectedTab === "Events" ? EventsScreen : LogsScreen;
96+
97+
return (
98+
<View style={styles.webTabs}>
99+
<View style={styles.webTabContent}>
100+
<ActiveScreen />
101+
</View>
102+
<View style={styles.webTabBar}>
103+
{appTabs.map((tab) => (
104+
<Pressable
105+
key={tab.key}
106+
accessibilityRole="tab"
107+
accessibilityState={{ selected: selectedTab === tab.key }}
108+
onPress={() => setSelectedTab(tab.key)}
109+
style={styles.webTabButton}
110+
>
111+
<Text style={[styles.webTabLabel, selectedTab === tab.key && styles.webTabLabelActive]}>{tab.title}</Text>
112+
</Pressable>
113+
))}
114+
</View>
115+
</View>
116+
);
117+
}
118+
119+
return (
120+
<Tabs.Host
121+
colorScheme="light"
122+
ios={{
123+
tabBarControllerMode: "tabBar",
124+
tabBarMinimizeBehavior: "never",
125+
tabBarTintColor: "#0f172a"
126+
}}
127+
nativeContainerStyle={styles.nativeTabsContainer}
128+
navStateRequest={navStateRequest}
129+
onTabSelected={handleTabSelected}
130+
rejectStaleNavStateUpdates
131+
>
132+
{appTabs.map((tab) => {
133+
const Screen = tab.key === "Errors" ? ErrorsScreen : tab.key === "Events" ? EventsScreen : LogsScreen;
134+
135+
return (
136+
<Tabs.Screen ios={{ icon: { name: tab.icon, type: "sfSymbol" } }} key={tab.key} screenKey={tab.key} style={styles.nativeTabScreen} title={tab.title}>
137+
<Screen />
138+
</Tabs.Screen>
139+
);
140+
})}
141+
</Tabs.Host>
142+
);
143+
}
144+
90145
export default function App() {
91146
useEffect(() => {
92147
void Exceptionless.startup((config) => {
@@ -101,47 +156,11 @@ export default function App() {
101156

102157
return (
103158
<SafeAreaProvider>
104-
<NavigationContainer>
105-
<View style={styles.appShell}>
106-
<TopDiagnostics />
107-
<Tab.Navigator
108-
screenOptions={{
109-
headerShown: false,
110-
tabBarActiveTintColor: "#0f172a",
111-
tabBarInactiveTintColor: "#64748b",
112-
tabBarLabelStyle: styles.tabLabel,
113-
tabBarStyle: styles.tabBar,
114-
tabBarBackground: () => <GlassView glassEffectStyle="regular" isInteractive style={StyleSheet.absoluteFill} tintColor="rgba(255,255,255,0.58)" />
115-
}}
116-
>
117-
<Tab.Screen
118-
name="Errors"
119-
component={ErrorsScreen}
120-
options={{
121-
title: "Errors",
122-
tabBarIcon: ({ focused }) => <TabIcon label="!" focused={focused} />
123-
}}
124-
/>
125-
<Tab.Screen
126-
name="Events"
127-
component={EventsScreen}
128-
options={{
129-
title: "Events",
130-
tabBarIcon: ({ focused }) => <TabIcon label="|" focused={focused} />
131-
}}
132-
/>
133-
<Tab.Screen
134-
name="Logs"
135-
component={LogsScreen}
136-
options={{
137-
title: "Logs",
138-
tabBarIcon: ({ focused }) => <TabIcon label="#" focused={focused} />
139-
}}
140-
/>
141-
</Tab.Navigator>
142-
</View>
143-
<StatusBar style="auto" />
144-
</NavigationContainer>
159+
<View style={styles.appShell}>
160+
<TopDiagnostics />
161+
<NativeTabs />
162+
</View>
163+
<StatusBar style="auto" />
145164
</SafeAreaProvider>
146165
);
147166
}
@@ -210,31 +229,40 @@ const styles = StyleSheet.create({
210229
lineHeight: 15,
211230
marginTop: 8
212231
},
213-
tabBar: {
214-
backgroundColor: "rgba(255,255,255,0.5)",
215-
borderTopColor: "rgba(148,163,184,0.22)",
232+
nativeTabsContainer: {
233+
backgroundColor: "#fff"
234+
},
235+
nativeTabScreen: {
236+
backgroundColor: "#fff"
237+
},
238+
webTabs: {
239+
flex: 1
240+
},
241+
webTabBar: {
242+
alignItems: "center",
243+
backgroundColor: "rgba(255,255,255,0.92)",
244+
borderTopColor: "#e5e7eb",
216245
borderTopWidth: StyleSheet.hairlineWidth,
217-
elevation: 0,
218-
height: 78,
219-
paddingBottom: 14,
220-
paddingTop: 8,
221-
position: "absolute",
222-
shadowColor: "#0f172a",
223-
shadowOffset: { height: -4, width: 0 },
224-
shadowOpacity: 0.08,
225-
shadowRadius: 18
226-
},
227-
tabIcon: {
228-
color: "#64748b",
229-
fontSize: 18,
230-
fontWeight: "800",
231-
lineHeight: 20
246+
flexDirection: "row",
247+
minHeight: 72,
248+
paddingBottom: 12,
249+
paddingTop: 8
232250
},
233-
tabIconFocused: {
234-
color: "#0f172a"
251+
webTabButton: {
252+
alignItems: "center",
253+
flex: 1,
254+
justifyContent: "center",
255+
minHeight: 44
235256
},
236-
tabLabel: {
257+
webTabContent: {
258+
flex: 1
259+
},
260+
webTabLabel: {
261+
color: "#64748b",
237262
fontSize: 12,
238263
fontWeight: "700"
264+
},
265+
webTabLabelActive: {
266+
color: "#0f172a"
239267
}
240268
});

example/nextjs/README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,14 @@ This sticks to the native Next.js file boundaries instead of inventing another f
3737

3838
### Environment variables
3939

40-
Set the env vars you want the example to use:
40+
By default, the example uses the same local development Exceptionless project as the other samples:
41+
42+
```js
43+
c.apiKey = "LhhP1C9gijpSKCslHHCvwdSIz298twx271nTest";
44+
c.serverUrl = "https://ex.dev.localhost:7111";
45+
```
46+
47+
Set these env vars if you want the example to use a different project or server:
4148

4249
- `NEXT_PUBLIC_EXCEPTIONLESS_API_KEY`
4350
- `NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL`

example/nextjs/lib/exceptionless-browser.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@ import { Exceptionless, KnownEventDataKeys } from "@exceptionless/browser";
22

33
export { Exceptionless };
44

5+
const DEFAULT_API_KEY = "LhhP1C9gijpSKCslHHCvwdSIz298twx271nTest";
6+
const DEFAULT_SERVER_URL = "https://ex.dev.localhost:7111";
7+
58
let startupPromise;
69

710
export function startup() {
811
startupPromise ??= Exceptionless.startup((config) => {
9-
if (process.env.NEXT_PUBLIC_EXCEPTIONLESS_API_KEY) {
10-
config.apiKey = process.env.NEXT_PUBLIC_EXCEPTIONLESS_API_KEY;
11-
}
12-
13-
if (process.env.NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL) {
14-
config.serverUrl = process.env.NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL;
15-
}
12+
config.apiKey = (process.env.NEXT_PUBLIC_EXCEPTIONLESS_API_KEY || DEFAULT_API_KEY).trim();
13+
config.serverUrl = (process.env.NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL || DEFAULT_SERVER_URL).trim();
1614

1715
if (process.env.NODE_ENV !== "production") {
1816
config.useDebugLogger();

example/nextjs/lib/exceptionless-server.js

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,15 @@ import { Exceptionless, KnownEventDataKeys, toError } from "@exceptionless/node"
22

33
export { Exceptionless, KnownEventDataKeys, toError };
44

5+
const DEFAULT_API_KEY = "LhhP1C9gijpSKCslHHCvwdSIz298twx271nTest";
6+
const DEFAULT_SERVER_URL = "https://ex.dev.localhost:7111";
7+
58
let startupPromise;
69

710
export async function startup() {
811
startupPromise ??= Exceptionless.startup((config) => {
9-
const apiKey = (process.env.EXCEPTIONLESS_API_KEY || process.env.NEXT_PUBLIC_EXCEPTIONLESS_API_KEY || "").trim();
10-
if (apiKey) {
11-
config.apiKey = apiKey;
12-
}
13-
14-
const serverUrl = (process.env.EXCEPTIONLESS_SERVER_URL || process.env.NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL || "").trim();
15-
if (serverUrl) {
16-
config.serverUrl = serverUrl;
17-
}
12+
config.apiKey = (process.env.EXCEPTIONLESS_API_KEY || process.env.NEXT_PUBLIC_EXCEPTIONLESS_API_KEY || DEFAULT_API_KEY).trim();
13+
config.serverUrl = (process.env.EXCEPTIONLESS_SERVER_URL || process.env.NEXT_PUBLIC_EXCEPTIONLESS_SERVER_URL || DEFAULT_SERVER_URL).trim();
1814

1915
if (process.env.NODE_ENV !== "production") {
2016
config.useDebugLogger();

0 commit comments

Comments
 (0)