1import * as NavigationBar from 'expo-navigation-bar';
2import * as React from 'react';
3import { Platform, ScrollView, Text } from 'react-native';
4import { useSafeAreaFrame, useSafeAreaInsets } from 'react-native-safe-area-context';
5
6import Button from '../components/Button';
7import { Page, Section } from '../components/Page';
8import { getRandomColor } from '../utilities/getRandomColor';
9
10function usePosition(): [
11  NavigationBar.NavigationBarPosition | null,
12  (position: NavigationBar.NavigationBarPosition) => void,
13] {
14  const [position, setPosition] = React.useState<NavigationBar.NavigationBarPosition | null>(null);
15
16  React.useEffect(() => {
17    let isMounted = true;
18    NavigationBar.unstable_getPositionAsync().then((position) => {
19      if (isMounted) {
20        setPosition(position);
21      }
22    });
23
24    return () => {
25      isMounted = false;
26    };
27  }, []);
28
29  const setNewPosition = React.useCallback(
30    (position: NavigationBar.NavigationBarPosition) => {
31      NavigationBar.setPositionAsync(position);
32      setPosition(position);
33    },
34    [setPosition]
35  );
36
37  return [position, setNewPosition];
38}
39
40export default function NavigationBarScreen() {
41  return (
42    <ScrollView>
43      <Page>
44        {Platform.OS !== 'android' && (
45          <Text style={{ marginVertical: 8, fontSize: 16 }}>⚠️ NavigationBar is Android-only</Text>
46        )}
47        <Section title="Visibility">
48          <VisibilityExample />
49        </Section>
50        <Section title="Appearance">
51          <ButtonStyleExample />
52        </Section>
53        <Section title="Background Color">
54          <BackgroundColorExample />
55        </Section>
56        <Section title="Border Color">
57          <BorderColorExample />
58        </Section>
59        <Section title="Position">
60          <PositionExample />
61        </Section>
62        <Section title="Behavior">
63          <BehaviorExample />
64        </Section>
65      </Page>
66    </ScrollView>
67  );
68}
69
70NavigationBarScreen.navigationOptions = {
71  title: 'Navigation Bar',
72};
73
74function VisibilityExample() {
75  const visibility = NavigationBar.useVisibility();
76  const nextVisibility = visibility === 'visible' ? 'hidden' : 'visible';
77  return (
78    <Button
79      title={`Toggle Visibility: ${nextVisibility}`}
80      onPress={() => {
81        NavigationBar.setVisibilityAsync(nextVisibility);
82      }}
83    />
84  );
85}
86
87function BackgroundColorExample() {
88  return (
89    <Button
90      onPress={() => NavigationBar.setBackgroundColorAsync(getRandomColor())}
91      title="Set background color to random color"
92    />
93  );
94}
95
96function BorderColorExample() {
97  return (
98    <Button
99      onPress={() => NavigationBar.setBorderColorAsync(getRandomColor())}
100      title="Set border color to random color"
101    />
102  );
103}
104
105function ButtonStyleExample() {
106  const [style, setStyle] = React.useState<NavigationBar.NavigationBarButtonStyle>('light');
107  const nextStyle = style === 'light' ? 'dark' : 'light';
108  return (
109    <Button
110      onPress={() => {
111        NavigationBar.setButtonStyleAsync(nextStyle);
112        setStyle(nextStyle);
113      }}
114      title={`Toggle bar style: ${nextStyle}`}
115    />
116  );
117}
118
119const NavigationBarBehaviors: NavigationBar.NavigationBarBehavior[] = [
120  'inset-swipe',
121  'inset-touch',
122  'overlay-swipe',
123];
124
125function PositionExample() {
126  const [position, setPosition] = usePosition();
127
128  const insets = useSafeAreaInsets();
129  const frame = useSafeAreaFrame();
130
131  return (
132    <>
133      <Button
134        onPress={() => setPosition(position === 'absolute' ? 'relative' : 'absolute')}
135        title={`Position: ${position === 'absolute' ? 'relative' : 'absolute'}`}
136      />
137      <Text>insets: {JSON.stringify(insets)}</Text>
138      <Text>frame: {JSON.stringify(frame)}</Text>
139    </>
140  );
141}
142
143function BehaviorExample() {
144  const [behavior, setBehavior] =
145    React.useState<NavigationBar.NavigationBarBehavior>('inset-swipe');
146
147  const nextNavigationBarBehavior = React.useMemo(() => {
148    const index = NavigationBarBehaviors.indexOf(behavior);
149    const newIndex = (index + 1) % NavigationBarBehaviors.length;
150    return NavigationBarBehaviors[newIndex];
151  }, [behavior]);
152
153  const onPressBehavior = React.useCallback(() => {
154    NavigationBar.setBehaviorAsync(nextNavigationBarBehavior);
155    setBehavior(nextNavigationBarBehavior);
156  }, [nextNavigationBarBehavior]);
157
158  return <Button onPress={onPressBehavior} title={`Behavior: ${nextNavigationBarBehavior}`} />;
159}
160