Skip to content

Commit 165ef78

Browse files
authored
Implement Help tab, and added some shortcuts (#21)
* implement help screen and some hotkeys: * fix key * fix app creating many menu items * fix style * fix light/dark switch
1 parent 934f29b commit 165ef78

19 files changed

+224
-1
lines changed

app/app.tsx

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ import { Titlebar } from "./components/Titlebar"
1414
import { Sidebar } from "./components/Sidebar/Sidebar"
1515
import { useSidebar } from "./state/useSidebar"
1616
import { AppHeader } from "./components/AppHeader"
17+
import { useGlobal, withGlobal } from "./state/useGlobal"
18+
import { MenuItemId } from "./components/Sidebar/SidebarMenu"
19+
import { HelpScreen } from "./screens/HelpScreen"
20+
import { TimelineItem } from "./types"
1721
import { PortalHost } from "./components/Portal"
1822

1923
if (__DEV__) {
@@ -25,6 +29,13 @@ if (__DEV__) {
2529
function App(): React.JSX.Element {
2630
const { colors } = useTheme()
2731
const { toggleSidebar } = useSidebar()
32+
const [activeItem, setActiveItem] = useGlobal<MenuItemId>("sidebar-active-item", "logs", {
33+
persist: true,
34+
})
35+
const [, setTimelineItems] = withGlobal<TimelineItem[]>("timelineItems", [], {
36+
persist: true,
37+
})
38+
2839
const menuConfig = useMemo(
2940
() => ({
3041
remove: ["File", "Edit", "Format"],
@@ -35,6 +46,31 @@ function App(): React.JSX.Element {
3546
shortcut: "cmd+b",
3647
action: toggleSidebar,
3748
},
49+
{
50+
label: "Logs Tab",
51+
shortcut: "cmd+1",
52+
action: () => setActiveItem("logs"),
53+
},
54+
{
55+
label: "Network Tab",
56+
shortcut: "cmd+2",
57+
action: () => setActiveItem("network"),
58+
},
59+
{
60+
label: "Performance Tab",
61+
shortcut: "cmd+3",
62+
action: () => setActiveItem("performance"),
63+
},
64+
{
65+
label: "Plugins Tab",
66+
shortcut: "cmd+4",
67+
action: () => setActiveItem("plugins"),
68+
},
69+
{
70+
label: "Help Tab",
71+
shortcut: "cmd+5",
72+
action: () => setActiveItem("help"),
73+
},
3874
...(__DEV__
3975
? [
4076
{
@@ -52,6 +88,13 @@ function App(): React.JSX.Element {
5288
action: () => DevSettings.reload(),
5389
},
5490
],
91+
Tools: [
92+
{
93+
label: "Clear Timeline Items",
94+
shortcut: "cmd+k",
95+
action: () => setTimelineItems([]),
96+
},
97+
],
5598
},
5699
}),
57100
[toggleSidebar],
@@ -80,7 +123,7 @@ function App(): React.JSX.Element {
80123
<Sidebar />
81124
<View style={$contentContainer}>
82125
<AppHeader />
83-
<TimelineScreen />
126+
{activeItem === "help" ? <HelpScreen /> : <TimelineScreen />}
84127
</View>
85128
</View>
86129
<PortalHost />

app/components/Icon.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ export const iconRegistry = {
7272
scrollText: require("../../assets/icons/scrollText.png"),
7373
chevronsLeftRightEllipsis: require("../../assets/icons/chevronsLeftRightEllipsis.png"),
7474
circleGauge: require("../../assets/icons/circleGauge.png"),
75+
questionMark: require("../../assets/icons/questionMark.png"),
76+
gitHub: require("../../assets/icons/gitHub.png"),
77+
messageSquare: require("../../assets/icons/messageSquare.png"),
78+
squirrel: require("../../assets/icons/squirrel.png"),
79+
xLogo: require("../../assets/icons/xLogo.png"),
7580
}
7681

7782
const $imageStyleBase: ImageStyle = {

app/components/Sidebar/SidebarMenu.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const MENU_ITEMS = [
88
{ id: "network", label: "Network", icon: "chevronsLeftRightEllipsis" },
99
{ id: "performance", label: "Performance", icon: "circleGauge" },
1010
{ id: "plugins", label: "Plugins", icon: "plug" },
11+
{ id: "help", label: "Help", icon: "questionMark" },
1112
] as const
1213

1314
export type MenuItemId = (typeof MENU_ITEMS)[number]["id"]

app/screens/HelpScreen.tsx

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
import { View, Text, ViewStyle, TextStyle, Pressable, Linking, ScrollView } from "react-native"
2+
import { themed, useThemeName } from "../theme/theme"
3+
import { Icon, IconTypes } from "../components/Icon"
4+
5+
export function HelpScreen() {
6+
return (
7+
<ScrollView style={$container()}>
8+
<View style={$connectContainer()}>
9+
<Text style={$title()}>{"Let's Connect!"}</Text>
10+
<View style={$divider()} />
11+
<View style={$connectRow()}>
12+
<ConnectItem
13+
icon="gitHub"
14+
title="GitHub Docs"
15+
url="https://github.com/infinitered/reactotron"
16+
/>
17+
<ConnectItem
18+
icon="messageSquare"
19+
title="Feedback"
20+
url="https://github.com/infinitered/reactotron/issues/new/choose"
21+
/>
22+
<ConnectItem
23+
icon="squirrel"
24+
title="Updates"
25+
url="https://github.com/infinitered/reactotron/releases"
26+
/>
27+
<ConnectItem icon="xLogo" title="@reactotron" url="https://x.com/reactotron" />
28+
</View>
29+
<Text style={$title()}>Keystrokes</Text>
30+
<View style={$divider()} />
31+
<View style={$keystrokesContainer()}>
32+
<Text style={$keystrokeSectionTitle()}>Navigation</Text>
33+
<KeystrokeItem title="Toggle Sidebar" keystrokes={["⌘", "b"]} />
34+
{__DEV__ ? <KeystrokeItem title="Toggle Dev Menu" keystrokes={["⇧", "⌘", "d"]} /> : null}
35+
<KeystrokeItem title="Logs Tab" keystrokes={["⌘", "1"]} />
36+
<KeystrokeItem title="Network Tab" keystrokes={["⌘", "2"]} />
37+
<KeystrokeItem title="Performance Tab" keystrokes={["⌘", "3"]} />
38+
<KeystrokeItem title="Plugins Tab" keystrokes={["⌘", "4"]} />
39+
<KeystrokeItem title="Help Tab" keystrokes={["⌘", "5"]} />
40+
<Text style={$keystrokeSectionTitle()}>Timeline</Text>
41+
<KeystrokeItem title="Clear Timeline Items" keystrokes={["⌘", "k"]} />
42+
</View>
43+
</View>
44+
</ScrollView>
45+
)
46+
}
47+
48+
function KeystrokeItem({ title, keystrokes }: { title: string; keystrokes: string[] }) {
49+
return (
50+
<View style={$keystrokeRowContainer()}>
51+
<View style={$keystrokeKeysContainer()}>
52+
{keystrokes.map((keystroke, index) => (
53+
<View key={`${title}-${keystroke}`} style={$keystrokeContainer()}>
54+
<View style={$keystrokeKey()}>
55+
<Text style={$keystroke()}>{keystroke}</Text>
56+
</View>
57+
{index !== keystrokes.length - 1 && <Text style={$keystroke()}>+</Text>}
58+
</View>
59+
))}
60+
</View>
61+
<Text style={$keystroke()}>{title}</Text>
62+
</View>
63+
)
64+
}
65+
66+
function ConnectItem({ icon, title, url }: { icon: IconTypes; title: string; url: string }) {
67+
const [themeName] = useThemeName()
68+
return (
69+
<Pressable style={$connectItem()} onPress={() => Linking.openURL(url)}>
70+
{/* TODO: Hack to make the icon change color when theme changes */}
71+
<Icon icon={icon} size={24} key={`${themeName}-icon`} />
72+
<Text style={$connectItemTitle()}>{title}</Text>
73+
</Pressable>
74+
)
75+
}
76+
77+
const $connectItemTitle = themed<TextStyle>(({ colors, spacing }) => ({
78+
fontSize: 16,
79+
fontWeight: "bold",
80+
color: colors.mainText,
81+
marginTop: spacing.sm,
82+
}))
83+
84+
const $title = themed<TextStyle>(({ colors, typography, spacing }) => ({
85+
fontSize: 20,
86+
fontWeight: "bold",
87+
color: colors.mainText,
88+
fontFamily: typography.code.normal,
89+
marginTop: spacing.xl,
90+
}))
91+
92+
const $divider = themed<ViewStyle>(({ colors, spacing }) => ({
93+
height: 1,
94+
backgroundColor: colors.border,
95+
width: "100%",
96+
marginTop: spacing.md,
97+
}))
98+
99+
const $container = themed<ViewStyle>(({ spacing }) => ({
100+
padding: spacing.xl,
101+
flex: 1,
102+
}))
103+
104+
const $connectContainer = themed<ViewStyle>(({ spacing }) => ({
105+
paddingHorizontal: spacing.xl,
106+
paddingBottom: spacing.xl,
107+
}))
108+
109+
const $connectRow = themed<ViewStyle>(({ spacing }) => ({
110+
flexDirection: "row",
111+
justifyContent: "space-between",
112+
alignItems: "center",
113+
gap: spacing.md,
114+
marginTop: spacing.xl,
115+
flexWrap: "wrap",
116+
}))
117+
118+
const $connectItem = themed<ViewStyle>(({ spacing, colors }) => ({
119+
padding: spacing.xl,
120+
justifyContent: "center",
121+
alignItems: "center",
122+
backgroundColor: colors.cardBackground,
123+
borderRadius: 8,
124+
flex: 1,
125+
minWidth: 160,
126+
}))
127+
128+
const $keystrokesContainer = themed<ViewStyle>(({ spacing }) => ({
129+
justifyContent: "space-between",
130+
gap: spacing.md,
131+
}))
132+
133+
const $keystrokeKey = themed<ViewStyle>(({ spacing, colors }) => ({
134+
padding: spacing.xs,
135+
backgroundColor: colors.cardBackground,
136+
borderRadius: 8,
137+
width: 40,
138+
height: 40,
139+
justifyContent: "center",
140+
alignItems: "center",
141+
}))
142+
143+
const $keystroke = themed<TextStyle>(({ colors, spacing }) => ({
144+
fontSize: 16,
145+
fontWeight: "bold",
146+
color: colors.mainText,
147+
}))
148+
149+
const $keystrokeContainer = themed<ViewStyle>(({ spacing }) => ({
150+
flexDirection: "row",
151+
alignItems: "center",
152+
gap: spacing.xs,
153+
}))
154+
155+
const $keystrokeKeysContainer = themed<ViewStyle>(({ spacing }) => ({
156+
flexDirection: "row",
157+
alignItems: "center",
158+
gap: spacing.xs,
159+
}))
160+
161+
const $keystrokeSectionTitle = themed<TextStyle>(({ colors, spacing }) => ({
162+
fontSize: 16,
163+
fontWeight: "bold",
164+
color: colors.neutral,
165+
marginTop: spacing.xl,
166+
}))
167+
168+
const $keystrokeRowContainer = themed<ViewStyle>(({ spacing }) => ({
169+
flexDirection: "row",
170+
justifyContent: "space-between",
171+
alignItems: "center",
172+
gap: spacing.md,
173+
width: 400,
174+
}))

assets/icons/gitHub.png

390 Bytes
Loading

assets/icons/gitHub@2x.png

722 Bytes
Loading

assets/icons/gitHub@3x.png

1.06 KB
Loading

assets/icons/messageSquare.png

227 Bytes
Loading

assets/icons/messageSquare@2x.png

355 Bytes
Loading

assets/icons/messageSquare@3x.png

517 Bytes
Loading

0 commit comments

Comments
 (0)