Drawer.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740
  1. /**
  2. * 首页抽屉菜单
  3. * @邠心vbe on 2021/03/23
  4. */
  5. import React, { Component } from 'react';
  6. import {View, Text, StyleSheet, Image, Pressable, BackHandler, Linking, Touchable} from 'react-native';
  7. import { createDrawerNavigator, DrawerContentScrollView } from '@react-navigation/drawer';
  8. import { Styles } from '../../components/Toolbar';
  9. import app from '../../../app.json';
  10. import Maps from './Home';
  11. import { PageList } from '../Router';
  12. import Dialog from '../../components/Dialog';
  13. import { host, setAccessToken } from '../../api/http';
  14. import { getStorageJsonSync, setStorage, setStorageJson } from '../../utils/storage';
  15. import Button from '../../components/Button';
  16. import { AutoLogin } from '../sign/Login';
  17. import apiCharge from '../../api/apiCharge';
  18. import { TouchableWithoutFeedback } from 'react-native-gesture-handler';
  19. import { toTopupPage } from '../payment/PaymentConfig';
  20. import utils from '../../utils/utils';
  21. import apiNotification from '../../api/apiNotification';
  22. import TextRadius from '../../components/TextRadius';
  23. const Drawer = createDrawerNavigator();
  24. const DEBUG = app.debug && !app.product;
  25. export default class Home extends Component {
  26. constructor(props) {
  27. super(props);
  28. this.state = {
  29. isLogin: false,
  30. userInfo: {},
  31. notificationCount: 0
  32. }
  33. }
  34. componentDidMount() {
  35. AutoLogin(() => {
  36. this.setState({
  37. userInfo: userInfo
  38. });
  39. });
  40. this.props.navigation.addListener('focus', () => {
  41. //console.log('drawer focus');
  42. getUserInfo(info => {
  43. this.setState({
  44. userInfo: info
  45. });
  46. }, true);
  47. if (app.modules.notifications && this.state.isLogin) {
  48. this.getNotificationTotal();
  49. }
  50. });
  51. /*BackHandler.addEventListener('hardwareBackPress', (e) => {
  52. if (global.dialogId !== 0) {
  53. Dialog.dismissLoading();
  54. return true;
  55. }
  56. return false;
  57. })*/
  58. }
  59. componentDidUpdate() {
  60. const status = isLogin();
  61. if (this.state.isLogin != status) {
  62. this.setState({
  63. isLogin: status
  64. }, () => {
  65. getUserInfo(info => {
  66. this.setState({
  67. userInfo: info
  68. });
  69. if (info.firebaseToken) {
  70. let token = isIOS ? info.firebaseToken?.ios : info.firebaseToken?.android
  71. if (notifyToken.token) {
  72. utils.registerFirebaseToken(token ?? "");
  73. }
  74. }
  75. }, true);
  76. if (app.modules.notifications) {
  77. this.getNotificationTotal();
  78. }
  79. });
  80. }
  81. }
  82. async requestLogout() {
  83. const data = await getStorageJsonSync('loginData');
  84. if (data && data.email) {
  85. delete data.password
  86. setStorageJson('loginData', data);
  87. setStorage('RegisterTokenDate', "");
  88. }
  89. global.userInfo = {}
  90. this.setState({
  91. isLogin: false,
  92. userInfo: {}
  93. });
  94. setAccessToken('');
  95. Dialog.dismissLoading();
  96. }
  97. getNotificationTotal() {
  98. apiNotification.getUnreadTotal().then(res => {
  99. if (res.data) {
  100. this.setState({
  101. notificationCount: res.data?.toBeReadCount ?? 0
  102. })
  103. } else {
  104. this.setState({
  105. notificationCount: 0
  106. })
  107. }
  108. }).catch(err => {
  109. this.setState({
  110. notificationCount: 0
  111. })
  112. })
  113. }
  114. render () {
  115. return (
  116. <Drawer.Navigator
  117. initialRouteName='maps'
  118. drawerContent={props =>
  119. <CustomerDrawerContent
  120. {...props}
  121. isLogin={this.state.isLogin}
  122. userInfo={this.state.userInfo}
  123. onLogout={() => this.requestLogout()}
  124. notificationCount={this.state.notificationCount}
  125. />
  126. }
  127. drawerType={
  128. global.$width >= 768 ? 'back' : 'front'
  129. }
  130. drawerStyle={{
  131. width: $vw(75) > 320 ? 320 : $vw(75),
  132. backgroundColor: colorLight
  133. }}>
  134. <Drawer.Screen name="maps" component={Maps} />
  135. </Drawer.Navigator>
  136. );
  137. }
  138. };
  139. const CustomerDrawerContent = (props) => {
  140. return (
  141. <DrawerContentScrollView
  142. {...props}
  143. canCancelContentTouches={true}>
  144. <DrawerContent {...props}/>
  145. </DrawerContentScrollView>
  146. );
  147. }
  148. const DrawerContent = ({isLogin, userInfo, onLogout, notificationCount=0, navigation}) => {
  149. const getCharging = () => {
  150. Dialog.showProgressDialog();
  151. apiCharge.getUserCharging().then(res => {
  152. Dialog.dismissLoading();
  153. if (res.data.sitePk) {
  154. startPage(PageList.chargeDetailPage, {stationInfo: {id: res.data.sitePk}, action: 'view', from: PageList.home});
  155. //startPage(PageList.chargeDetail, { stationInfo: {id: res.data.sitePk}, action: 'view'});
  156. } else if (res.msg) {
  157. toastShort(res.msg);
  158. } else {
  159. toastShort($t("drawer.noChargingSession"));
  160. }
  161. }).catch((err) => {
  162. if (app.debug)
  163. console.log(err);
  164. Dialog.dismissLoading();
  165. toastShort($t("drawer.noChargingSession"));
  166. })
  167. }
  168. const logout = () => {
  169. Dialog.showDialog({
  170. title: 'Sign out',
  171. message: 'Are you sure you want to sign out?',
  172. callback: btn => {
  173. if (btn == 'ok') {
  174. Dialog.showProgressDialog();
  175. setTimeout(() => {
  176. onLogout();
  177. }, 500);
  178. }
  179. }
  180. })
  181. }
  182. return (
  183. <View style={styles.drawerView}>
  184. <View style={styles.loginView}>
  185. { (isLogin && userInfo.photoUrl)
  186. ? <TouchableWithoutFeedback onPress={() => startPage(PageList.profile)}>
  187. <Image
  188. style={styles.avatar}
  189. source={{uri: host + userInfo.photoUrl}}/>
  190. </TouchableWithoutFeedback>
  191. : <TouchableWithoutFeedback onPress={() => startPage(PageList.login)}>
  192. <Image
  193. style={styles.avatar}
  194. source={require('../../images/user/ic-avatar-default.png')}/>
  195. </TouchableWithoutFeedback>
  196. }
  197. <Pressable
  198. style={styles.nickView}
  199. android_ripple={ripple}
  200. onPress={() => startPage(isLogin ? PageList.profile : PageList.login)}>
  201. <Text
  202. style={styles.nickname}
  203. ellipsizeMode='tail'
  204. numberOfLines={1}>
  205. { isLogin
  206. ? userInfo.nickName
  207. ? userInfo.nickName
  208. : $t('drawer.logging')
  209. : $t('drawer.sign')
  210. }
  211. </Text>
  212. <FontAwesome
  213. size={24}
  214. color='#999'
  215. name='angle-right'/>
  216. </Pressable>
  217. </View>
  218. <View style={styles.divideLogin}></View>
  219. {/* isLogin
  220. ? <Button
  221. style={styles.itemButton}
  222. viewStyle={styles.itemView}
  223. onClick={() => {
  224. startPage(PageList.profile)
  225. }}>
  226. <Image
  227. style={styles.icon}
  228. source={require('../../images/icon/draw-user.png')}/>
  229. <Text style={styles.label}>Profile Settings</Text>
  230. </Button>
  231. : <Button
  232. style={styles.itemButton}
  233. viewStyle={styles.itemView}
  234. onClick={() => {
  235. startPage(PageList.login);
  236. }}>
  237. <Image
  238. style={styles.icon}
  239. source={require('../../images/icon/draw-user.png')}/>
  240. <Text style={styles.label}>Sign In</Text>
  241. </Button>
  242. */}
  243. {/* <Button
  244. style={styles.itemButton}
  245. viewStyle={styles.itemView}
  246. onClick={() => {
  247. navigation.toggleDrawer();
  248. }}>
  249. <Image
  250. style={styles.icon}
  251. source={require('../../images/icon/draw-home.png')}/>
  252. <Text style={styles.label}>Home</Text>
  253. </Button> */}
  254. { isLogin
  255. ? <Button
  256. style={styles.itemButton}
  257. viewStyle={styles.itemView}
  258. onClick={() => getCharging()}>
  259. <MaterialCommunityIcons
  260. style={styles.icon}
  261. name="car-electric-outline"
  262. color="#333"
  263. size={26}
  264. />
  265. {/* <Image
  266. style={styles.icon}
  267. source={require('../../images/icon/draw-charge.png')}/> */}
  268. <Text style={styles.label}>{$t('drawer.charging')}</Text>
  269. </Button>
  270. : <View
  271. style={styles.disableItem}>
  272. <MaterialCommunityIcons
  273. style={styles.icon}
  274. name="car-electric-outline"
  275. color="#999"
  276. size={26}
  277. />
  278. {/* <Image
  279. style={styles.icon}
  280. source={require('../../images/icon/draw-charge-no.png')}/> */}
  281. <Text style={styles.disable}>{$t('drawer.charging')}</Text>
  282. </View>
  283. }
  284. {/* isLogin
  285. ? <Button
  286. style={styles.itemButton}
  287. viewStyle={styles.itemView}
  288. onClick={() => {
  289. startPage(PageList.wallet);
  290. }}>
  291. <Image
  292. style={styles.icon}
  293. source={require('../../images/icon/draw-transaction.png')}/>
  294. <Text style={styles.label}>{$t('drawer.wallet')}</Text>
  295. </Button>
  296. : <View
  297. style={styles.disableItem}>
  298. <Image
  299. style={styles.icon}
  300. source={require('../../images/icon/draw-transaction-no.png')}/>
  301. <Text style={styles.disable}>{$t('drawer.wallet')}</Text>
  302. </View>
  303. */}
  304. {
  305. isLogin && <>
  306. <Button
  307. style={styles.itemButton}
  308. viewStyle={styles.itemView}
  309. onClick={() => {
  310. startPage(PageList.wallet);
  311. }}>
  312. <Image
  313. style={styles.icon}
  314. source={require('../../images/icon/draw-transaction.png')}/>
  315. <Text style={styles.label}>{$t('drawer.wallet')}</Text>
  316. </Button>
  317. <Button
  318. style={styles.itemButton}
  319. viewStyle={styles.itemView}
  320. onClick={() => toTopupPage()}>
  321. <MaterialCommunityIcons
  322. style={styles.icon}
  323. size={26}
  324. name={"wallet-outline"}
  325. color={colorDark}/>
  326. <Text style={styles.label}>{$t('drawer.topup')}</Text>
  327. <Text style={styles.balanceText2}>{currency}{userInfo.credit}</Text>
  328. </Button></>
  329. }
  330. {/*附加功能-开始*/}
  331. { (app.modules.notifications && isLogin) &&
  332. <Button
  333. style={styles.itemButton}
  334. viewStyle={styles.itemView}
  335. onClick={() => {
  336. startPage(PageList.notification);
  337. }}>
  338. <MaterialIcons
  339. style={styles.icon}
  340. name="notifications"
  341. color="#222"
  342. size={26}/>
  343. <Text style={styles.label}>{$t('route.notifications')}</Text>
  344. { notificationCount > 0 &&
  345. notificationCount < 100
  346. ? <TextRadius style={styles.bridgeText}>{notificationCount}</TextRadius>
  347. : <TextRadius style={styles.bridgeText2}>99+</TextRadius>
  348. }
  349. </Button>
  350. }
  351. { (app.modules.bookmarks && isLogin) &&
  352. <Button
  353. style={styles.itemButton}
  354. viewStyle={styles.itemView}
  355. onClick={() => {
  356. startPage(PageList.bookmarks);
  357. }}>
  358. <MaterialIcons
  359. style={styles.icon}
  360. name="stars"
  361. color="#222"
  362. size={26}/>
  363. <Text style={styles.label}>{$t('route.bookmarks')}</Text>
  364. </Button>
  365. }
  366. {/*附加功能-结束*/}
  367. { isLogin &&
  368. <Button
  369. style={styles.itemButton}
  370. viewStyle={styles.itemView}
  371. onClick={() => {
  372. startPage(PageList.membersList);
  373. }}>
  374. <MaterialIcons
  375. style={styles.icon}
  376. name="card-membership"
  377. color="#222"
  378. size={26}/>
  379. <Text style={styles.label}>{$t('drawer.members')}</Text>
  380. </Button>
  381. }
  382. <Button
  383. style={styles.itemButton}
  384. viewStyle={styles.itemView}
  385. onClick={() => {
  386. startPage(PageList.feedback);
  387. }}>
  388. <MaterialCommunityIcons
  389. style={styles.icon2}
  390. name="message-alert-outline"
  391. color="#222"
  392. size={24}/>
  393. <Text style={styles.label}>{$t('drawer.feedback')}</Text>
  394. </Button>
  395. {/* <Button
  396. style={styles.itemButton}
  397. viewStyle={styles.itemView}
  398. onClick={() => {
  399. Linking.openURL(host+"juicePicture/pdf/FAQ.v1.0.pdf")
  400. }}>
  401. <Feather
  402. style={styles.icon2}
  403. name="download"
  404. color={colorDark}
  405. size={24}
  406. />
  407. <Text style={styles.label}>FAQs</Text>
  408. </Button> */}
  409. <Button
  410. style={styles.itemButton}
  411. viewStyle={styles.itemView}
  412. onClick={() => {
  413. startPage(PageList.settings);
  414. }}>
  415. <Ionicons
  416. style={styles.icon}
  417. name="md-settings-outline"
  418. color="#222"
  419. size={25}
  420. />
  421. <Text style={styles.label}>{$t('drawer.settings')}</Text>
  422. </Button>
  423. { app.modules.support &&
  424. <Button
  425. style={styles.itemButton}
  426. viewStyle={styles.itemView}
  427. onClick={() => {
  428. startPage(PageList.supportContact);
  429. }}>
  430. <MaterialCommunityIcons
  431. style={styles.icon}
  432. name="face-agent"
  433. color="#333"
  434. size={26}
  435. />
  436. <Text style={styles.label}>{$t('drawer.contactSupport')}</Text>
  437. </Button>
  438. }
  439. <Button
  440. style={styles.itemButton}
  441. viewStyle={styles.itemView}
  442. onClick={() => {
  443. startPage(PageList.about);
  444. }}>
  445. <MaterialCommunityIcons
  446. style={styles.icon}
  447. name="information-outline"
  448. color="#333"
  449. size={26}
  450. />
  451. <Text style={styles.label}>{$t('drawer.about')}</Text>
  452. </Button>
  453. {/* <View style={styles.divided}></View> */}
  454. { DEBUG &&
  455. <>
  456. <View style={styles.divideLogin}></View>
  457. <Text style={{color: "#ccc", paddingLeft: 16, paddingBottom: 8, fontSize: 12}}>{$t('drawer.debugOnly')}</Text>
  458. <Button
  459. style={styles.itemButton}
  460. viewStyle={styles.itemView}
  461. onClick={() => {
  462. startPage(PageList.privacy);
  463. }}>
  464. <MaterialCommunityIcons
  465. style={styles.icon}
  466. name="file-eye-outline"
  467. color="#222"
  468. size={26}/>
  469. <Text style={styles.label}>{$t('drawer.privacyPolicy')}</Text>
  470. </Button>
  471. <Button
  472. style={styles.itemButton}
  473. viewStyle={styles.itemView}
  474. onClick={() => {
  475. startPage(PageList.condition);
  476. }}>
  477. <MaterialCommunityIcons
  478. style={styles.icon}
  479. name="file-eye-outline"
  480. color="#222"
  481. size={26}/>
  482. <Text style={styles.label}>{$t('drawer.termsOfUse')}</Text>
  483. </Button>
  484. <Button
  485. style={styles.itemButton}
  486. viewStyle={styles.itemView}
  487. onClick={() => {
  488. startPage(PageList.notify);
  489. }}>
  490. {/* <Image
  491. style={styles.icon2}
  492. source={require('../../images/icon/draw-terms.png')}/> */}
  493. <MaterialIcons
  494. style={styles.icon}
  495. name="notifications-none"
  496. color="#222"
  497. size={26}/>
  498. <Text style={styles.label}>{$t('route.notificationTest')}</Text>
  499. </Button>
  500. <Button
  501. style={styles.itemButton}
  502. viewStyle={styles.itemView}
  503. onClick={() => {
  504. startPage(isIOS ? PageList.notify : PageList.mapTest);
  505. }}>
  506. <MaterialCommunityIcons
  507. style={styles.icon}
  508. name="map-legend"
  509. color="#222"
  510. size={26}/>
  511. <Text style={styles.label}>{$t('drawer.mapsTest')}</Text>
  512. </Button>
  513. </>}
  514. {/* isLogin
  515. ? <View style={styles.walletView}>
  516. <Pressable
  517. style={styles.balanceView}
  518. android_ripple={ripple}
  519. onPress={() => toTopupPage()}>
  520. <Image
  521. style={styles.icon}
  522. source={require('../../images/icon/draw-wallet.png')}/>
  523. <Text style={styles.balanceText}>{currency}{userInfo.credit}</Text>
  524. </Pressable>
  525. {/* <Pressable
  526. style={styles.balanceView}
  527. android_ripple={ripple}
  528. onPress={() => {
  529. startPage(PageList.referral);
  530. }}>
  531. <Image
  532. style={styles.icon}
  533. source={require('../../images/icon/draw-gift.png')}/>
  534. <Text style={styles.referText}>Refer your friends to get $5 credit!</Text>
  535. </Pressable> *}
  536. </View>
  537. : <View style={ui.flex1}></View>s
  538. */}
  539. <View style={styles.bottomView}>
  540. <Image
  541. style={Styles.logo}
  542. resizeMode='contain'
  543. source={require('../../images/app-logo.png')}
  544. />
  545. <Text style={styles.versionText}>{app.displayName + ' ' + app.versionName}</Text>
  546. </View>
  547. {/* isLogin &&
  548. <Button
  549. style={styles.logoutView}
  550. text='Logout'
  551. textColor={textButton}
  552. borderRadius={0}
  553. onClick={() => logout()}/>
  554. */}
  555. </View>
  556. );
  557. }
  558. const styles = StyleSheet.create({
  559. drawerTop: {
  560. top: 0,
  561. left: 0,
  562. right: 0,
  563. height: statusHeight,
  564. position: 'absolute',
  565. fontSize: 10,
  566. backgroundColor: pageBackground
  567. },
  568. drawerView: {
  569. paddingTop: 16,
  570. paddingBottom: 8,
  571. minHeight: $vhs(101)
  572. },
  573. guessView: {
  574. padding: 16
  575. },
  576. loginView: {
  577. paddingTop: 16,
  578. paddingBottom: 8
  579. },
  580. avatar: {
  581. width: 66,
  582. height: 66,
  583. marginLeft: 24,
  584. borderWidth: 2,
  585. borderRadius: 80,
  586. borderColor: colorLight,
  587. },
  588. nickView: {
  589. marginTop: 4,
  590. flexDirection: 'row',
  591. ...$padding(12, 16)
  592. },
  593. nickname: {
  594. flex: 1,
  595. color: textPrimary,
  596. fontSize: 20,
  597. fontWeight: 'bold',
  598. paddingLeft: 16,
  599. },
  600. divideLogin: {
  601. height: 1,
  602. marginTop: 4,
  603. marginRight: 32,
  604. marginBottom: 12,
  605. backgroundColor: '#E5E5E5'
  606. },
  607. itemButton: {
  608. borderRadius: 0,
  609. backgroundColor: colorLight
  610. },
  611. itemView: {
  612. flex: 1,
  613. height: 56,
  614. paddingLeft: 16,
  615. marginBottom: 6,
  616. alignItems: 'center',
  617. flexDirection: 'row'
  618. },
  619. disableItem: {
  620. height: 56,
  621. paddingLeft: 16,
  622. marginBottom: 6,
  623. alignItems: 'center',
  624. flexDirection: 'row'
  625. },
  626. icon: {
  627. width: 26,
  628. height: 26,
  629. marginRight: 16
  630. },
  631. icon2: {
  632. width: 24,
  633. height: 24,
  634. marginLeft: 1,
  635. marginRight: 17
  636. },
  637. label: {
  638. flex: 1,
  639. color: textPrimary,
  640. fontSize: 16.5
  641. },
  642. disable: {
  643. color: '#999',
  644. fontSize: 18
  645. },
  646. divided: {
  647. height: 1,
  648. marginTop: 24,
  649. marginLeft: 16,
  650. backgroundColor: colorAccent
  651. },
  652. walletView: {
  653. paddingTop: 16,
  654. paddingLeft: 48,
  655. paddingRight: 48
  656. },
  657. balanceView: {
  658. marginTop: 16,
  659. borderRadius: 8,
  660. ...$padding(13, 22),
  661. alignItems: 'center',
  662. flexDirection: 'row',
  663. justifyContent: 'center',
  664. backgroundColor: 'rgba(0, 20, 137, 0.2)'
  665. },
  666. balanceText: {
  667. color: textPrimary,
  668. fontSize: 22,
  669. fontWeight: 'bold'
  670. },
  671. referText: {
  672. flex: 1,
  673. color: textPrimary,
  674. fontSize: 13
  675. },
  676. bottomView: {
  677. flex: 1,
  678. paddingTop: 48,
  679. paddingBottom: 0,
  680. alignItems: 'center',
  681. justifyContent: 'flex-end'
  682. },
  683. versionText: {
  684. color: textPrimary,
  685. fontSize: 10,
  686. paddingTop: 16
  687. },
  688. logoutView: {
  689. backgroundColor: colorPrimary
  690. },
  691. balanceText2: {
  692. color: textCancel,
  693. fontSize: 14,
  694. marginRight: 32
  695. },
  696. bridgeText: {
  697. width: 20,
  698. height: 20,
  699. color: textLight,
  700. fontSize: 12,
  701. lineHeight: 19,
  702. marginRight: 16,
  703. borderRadius: 20,
  704. fontWeight: 'bold',
  705. textAlign: 'center',
  706. backgroundColor: "#FF3B30"
  707. },
  708. bridgeText2: {
  709. width: 22,
  710. height: 22,
  711. color: textLight,
  712. fontSize: 10,
  713. lineHeight: 22,
  714. marginRight: 16,
  715. borderRadius: 22,
  716. fontWeight: 'bold',
  717. textAlign: 'center',
  718. backgroundColor: "#FF3B30"
  719. }
  720. });