index.js 5.4 KB
import React, {useState} from 'react';
import {StyleSheet, View} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';
import {
  BottomSheet,
  Divider,
  Icon,
  ListItem,
  Skeleton,
  Text,
} from '@rneui/themed';
import {Button, Chip} from '@rneui/base';
import api from '../../../api';
import {NodePlayerView} from 'react-native-nodemediaclient';
import {useSelector} from 'react-redux';
import {selectCameraById} from '../cameraSlice';

const Camera = ({route}) => {
  const [bottomSheetVisible, setBottomSheetVisible] = useState(false);
  const [channelList, setChannelList] = useState([]);
  const [channelInfo, setChannelInfo] = useState({});
  const [videoUri, setVideoUri] = useState(null);
  const [iconDisabled, setIconDisabled] = useState(false);
  const camera = useSelector(state => selectCameraById(state, route.params.id));

  const handleShowChannelList = async () => {
    if (route.params.deviceId) {
      const data = await api.cameras.getChannels(route.params.deviceId);
      if (data.code === 200) {
        setChannelList(data.results);
        setBottomSheetVisible(true);
      }
    }
  };

  const onSelectChannel = async channelItem => {
    setBottomSheetVisible(false);
    setChannelInfo(channelItem);
    const data = await api.cameras.getStream({
      deviceId: channelItem.deviceId,
      channelId: channelItem.channelId,
    });
    if (data.code === 200) {
      setVideoUri(data.result);
    }
  };

  const handlePtzControl = async direction => {
    const ptzInfo = {
      deviceId: route.params.deviceId,
      channelId: channelInfo.channelId,
      command: direction,
    };
    setIconDisabled(true);
    if (direction === 'stop') {
      const data = await api.cameras.ptzControl(ptzInfo);
      if (data?.code === 200) {
        setIconDisabled(false);
      }
    } else {
      const data = await api.cameras.ptzControl(direction);
      if (data?.code === 200) {
        setTimeout(async () => {
          const data1 = await api.cameras.ptzControl({
            deviceId: route.params.deviceId,
            channelId: channelInfo.channelId,
            command: 'stop',
          });
          if (data1?.code === 200) {
            setIconDisabled(false);
          }
        }, 1500);
      } else {
        setIconDisabled(false);
      }
    }
  };

  return (
    <SafeAreaView style={styles.contain}>
      <Text style={styles.title}>{camera.name || camera.deviceId}</Text>
      <Divider />
      <View style={styles.channel}>
        <Text style={styles.text}>通道:{channelInfo?.name}</Text>
        <Chip
          type="clear"
          title="选择通道"
          onPress={() => handleShowChannelList()}
        />
      </View>
      <Divider />
      {videoUri ? (
        <View style={styles.videoBox}>
          <NodePlayerView
            style={styles.video}
            inputUrl={videoUri}
            scaleMode={'ScaleAspectFit'}
            bufferTime={300}
            maxBufferTime={1000}
            autoplay={true}
          />
          <View style={styles.iconBox1}>
            <Icon
              name="keyboard-arrow-up"
              size={30}
              color="#1890ff"
              reverse
              disabled={iconDisabled}
              onPress={() => handlePtzControl('up')}
            />
          </View>
          <View style={styles.iconBox2}>
            <Icon
              name="keyboard-arrow-left"
              size={30}
              reverse
              color="#1890ff"
              disabled={iconDisabled}
              onPress={() => handlePtzControl('left')}
            />
            <Icon
              name="pause"
              size={40}
              onPress={() => handlePtzControl('stop')}
            />
            <Icon
              name="keyboard-arrow-right"
              size={30}
              reverse
              color="#1890ff"
              disabled={iconDisabled}
              onPress={() => handlePtzControl('right')}
            />
          </View>
          <View style={styles.iconBox1}>
            <Icon
              name="keyboard-arrow-down"
              size={30}
              reverse
              color="#1890ff"
              disabled={iconDisabled}
              onPress={() => handlePtzControl('right')}
            />
          </View>
        </View>
      ) : (
        <Skeleton height={350} animation="none" />
      )}
      <BottomSheet modalProps={{}} isVisible={bottomSheetVisible}>
        {channelList.map(l => (
          <ListItem key={l.channelId} onPress={() => onSelectChannel(l)}>
            <ListItem.Content>
              <ListItem.Title>{l?.name}</ListItem.Title>
            </ListItem.Content>
          </ListItem>
        ))}
        <Button title="取消" onPress={() => setBottomSheetVisible(false)} />
      </BottomSheet>
    </SafeAreaView>
  );
};

const styles = StyleSheet.create({
  contain: {
    backgroundColor: '#fff',
    minHeight: '100%',
  },
  title: {
    paddingLeft: 10,
    fontSize: 20,
    margin: 10,
  },
  channel: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingLeft: 20,
    paddingRight: 20,
    justifyContent: 'space-between',
  },
  text: {
    fontSize: 16,
  },
  videoBox: {
    padding: 10,
  },
  video: {
    height: 230,
  },
  iconBox1: {
    justifyContent: 'center',
    alignItems: 'center',
  },
  iconBox2: {
    padding: 20,
    flexDirection: 'row',
    alignItems: 'center',
    justifyContent: 'space-around',
  },
});

export default Camera;