1import Slider from '@react-native-community/slider';
2import * as Brightness from 'expo-brightness';
3import React from 'react';
4import { ScrollView, Text, View } from 'react-native';
5
6import Button from '../components/Button';
7import HeadingText from '../components/HeadingText';
8import { useResolvedValue } from '../utilities/useResolvedValue';
9
10const brightnessTypes: string[] = ['Brightness', 'SystemBrightness'];
11
12export default function BrightnessScreen() {
13  const [isAvailable, error] = useResolvedValue(Brightness.isAvailableAsync);
14
15  const warning = React.useMemo(() => {
16    if (error) {
17      return `An unknown error occurred while checking the API availability: ${error.message}`;
18    } else if (isAvailable === null) {
19      return 'Checking availability...';
20    } else if (isAvailable === false) {
21      return 'Brightness API is not available on this platform.';
22    }
23    return null;
24  }, [error, isAvailable]);
25
26  if (warning) {
27    return (
28      <View style={{ justifyContent: 'center', alignItems: 'center', flex: 1 }}>
29        <Text>{warning}</Text>
30      </View>
31    );
32  }
33
34  return <BrightnessView />;
35}
36
37function BrightnessView() {
38  const [brightness, setBrightness] = React.useState<number | null>(null);
39  const [systemBrightness] = useResolvedValue(Brightness.getSystemBrightnessAsync);
40  const [sliderBrightness, setSliderBrightness] = React.useState<Record<string, number>>({});
41
42  const [systemBrightnessPermissionGranted, setSystemBrightnessPermissionGranted] =
43    React.useState(false);
44
45  React.useEffect(() => {
46    async function initialize() {
47      const { granted } = await Brightness.getPermissionsAsync();
48      const brightness = await Brightness.getBrightnessAsync();
49      setSystemBrightnessPermissionGranted(granted);
50      setBrightness(brightness);
51    }
52
53    initialize();
54
55    const brightnessLevelListener = Brightness.addBrightnessListener(({ brightness }) => {
56      setBrightness(brightness);
57    });
58
59    return () => {
60      brightnessLevelListener.remove();
61    };
62  }, []);
63
64  function alertBrightnessAsync(type: string) {
65    (type === 'Brightness'
66      ? Brightness.getBrightnessAsync()
67      : Brightness.getSystemBrightnessAsync()
68    ).then((value) => {
69      alert(value);
70    });
71  }
72
73  function updateBrightnessAsync(value: number, type: string) {
74    setSliderBrightness((brightness) => ({ ...brightness, [type]: value }));
75    if (type === 'Brightness') {
76      Brightness.setBrightnessAsync(value);
77    } else {
78      Brightness.setSystemBrightnessAsync(value);
79    }
80  }
81
82  const initBrightness: Record<string, number | null> = {
83    Brightness: brightness,
84    SystemBrightness: systemBrightness,
85  };
86
87  const views = brightnessTypes.map((type) => {
88    const currentBrightness = initBrightness[type] ?? 0;
89    return (
90      <View key={type} style={{ padding: 20 }}>
91        <HeadingText>{type}</HeadingText>
92        {/* you can attempt to request permission even if already granted, but it will noop */}
93        {type === 'SystemBrightness' && (
94          <Button
95            title={`Request permissions ${
96              systemBrightnessPermissionGranted ? ' (already granted)' : ''
97            }`}
98            onPress={async () => {
99              const { granted } = await Brightness.requestPermissionsAsync();
100              setSystemBrightnessPermissionGranted(granted);
101            }}
102            style={{ marginTop: 15 }}
103          />
104        )}
105        <Button
106          title={'get' + type + 'Async'}
107          onPress={() => alertBrightnessAsync(type)}
108          style={{ marginTop: 15, marginBottom: 20 }}
109        />
110        <Text style={{ marginBottom: -2 }}>
111          {'set' + type + 'Async: '}
112          {(sliderBrightness[type] || currentBrightness).toFixed(3)}
113        </Text>
114        <Slider
115          value={currentBrightness}
116          disabled={type === 'SystemBrightness' && !systemBrightnessPermissionGranted}
117          onValueChange={(value) => updateBrightnessAsync(value, type)}
118        />
119      </View>
120    );
121  });
122  return <ScrollView style={{ flex: 1 }}>{views}</ScrollView>;
123}
124
125BrightnessScreen.navigationOptions = {
126  title: 'Brightness',
127};
128