IndexConsole.tsx 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011
  1. import { View, Text, Image, PageContainer } from '@tarojs/components'
  2. import './IndexConsole.scss'
  3. import { useTranslation } from 'react-i18next'
  4. import { useDispatch, useSelector } from 'react-redux';
  5. import { endFast, endSleep, getLocalPush, startFast, startSleep, uploadLocalPushInfo } from "../actions/TrackTimeActions";
  6. import { jumpPage } from '../hooks/Common';
  7. import { useContext, useEffect, useRef, useState } from 'react';
  8. import ConsolePicker from './ConsolePicker';
  9. import LimitPickers from '@/components/input/LimitPickers';
  10. import LimitTimeoutPickers from '@/components/input/LimitTimeoutPickers';
  11. import { getColor, getTimePickerTitle } from '../hooks/Console';
  12. import { kIsIOS, rpxToPx, vibrate } from '@/utils/tools';
  13. import { TimeFormatter } from '@/utils/time_format';
  14. import Modal from '@/components/layout/Modal.weapp';
  15. import Taro, { useDidShow } from '@tarojs/taro';
  16. import { wxPubFollow } from '@/services/permission';
  17. import { setWXFollow } from '@/store/permission';
  18. import CircadianDetailPopup from './CircadianDetailPopup';
  19. import showAlert from '@/components/basic/Alert';
  20. import CheckAccess from './CheckAccess';
  21. import { ColorType } from '@/context/themes/color';
  22. import IndexConsoleMuti from './IndexConsoleMuti';
  23. let useNavigation;
  24. let Linking, PushNotification;
  25. let checkNotification;
  26. if (process.env.TARO_ENV == 'rn') {
  27. useNavigation = require("@react-navigation/native").useNavigation
  28. Linking = require('react-native').Linking;
  29. // JPush = require('jpush-react-native').default;
  30. PushNotification = require('react-native-push-notification')
  31. checkNotification = require('@/utils/native_permission_check').checkNotification;
  32. }
  33. let operateType = ''
  34. let min = 0
  35. let max = 0
  36. let defaultTimestamp = 0
  37. let isTimeout = false
  38. let stageIndex = 0
  39. let nativePushListener = null
  40. export default function IndexConsole(props: { record: any, count: number, access: any }) {
  41. const user = useSelector((state: any) => state.user);
  42. const { status } = props.record.current_record;
  43. const currentRecord = props.record.current_record;
  44. const { t } = useTranslation()
  45. const [fastDuration, setFastDuration] = useState<number>(0);
  46. const [sleepDuration, setSleepDuration] = useState<number>(0);
  47. const [expand, setExpand] = useState(false);
  48. const permission = useSelector((state: any) => state.permission);
  49. const common = useSelector((state: any) => state.common);
  50. const [firstEnter, setFirstEnter] = useState(true);
  51. const dayMilliSeconds = 24 * 3600 * 1000;
  52. const [btnDisable, setBtnDisable] = useState(false)
  53. const [showStageModal, setShowStageModal] = useState(false)
  54. const [showTimePicker, setShowTimePicker] = useState(false);
  55. const [showMutiPicker, setShowMutiPicker] = useState(false);
  56. const [mutiEvent, setMutiEvent] = useState('start_fast');
  57. const dispatch = useDispatch();
  58. const limitPickerRef = useRef(null)
  59. let navigation;
  60. if (useNavigation) {
  61. navigation = useNavigation()
  62. }
  63. useDidShow(() => {
  64. if (process.env.TARO_ENV == 'weapp') {
  65. wxPubFollow({ force_refresh: true }).then(res => {
  66. dispatch(setWXFollow((res as any).wx_pub_followed));
  67. })
  68. }
  69. })
  70. useEffect(() => {
  71. if (process.env.TARO_ENV == 'rn') {
  72. // console.error('current status',status)
  73. var NativeAppEventEmitter = require('react-native').NativeAppEventEmitter;
  74. if (nativePushListener) {
  75. (nativePushListener as any).remove()
  76. }
  77. if (kIsIOS) {
  78. var Jto = require('react-native').NativeModules.NativeBridge;
  79. Jto.getNotificationAuthStatus()
  80. }
  81. nativePushListener = NativeAppEventEmitter.addListener('notificationReceive', (data) => {
  82. console.log('notification receive action', data)
  83. const { category_id, action_id, id } = data
  84. uploadLocalPushInfo({
  85. messageId: id
  86. })
  87. switch (action_id) {
  88. case 'START_TIMER_NOW':
  89. {
  90. if (category_id == 'REMINDER_FS_START_FAST') {
  91. operateType = 'startFast'
  92. }
  93. else {
  94. operateType = 'startSleep'
  95. }
  96. global.set_time = new Date().getTime()
  97. pickerConfirm(new Date().getTime())
  98. }
  99. break;
  100. case 'PICK_EARLIER_START':
  101. {
  102. if (category_id == 'REMINDER_FS_START_FAST') {
  103. tapStartFast(null)
  104. }
  105. else {
  106. tapStartSleep(null)
  107. }
  108. }
  109. break;
  110. case 'LOG_MY_TIMES':
  111. {
  112. if (category_id == 'REMINDER_FS_START_FAST_T2') {
  113. if (props.record.scenario.name == 'FAST_SLEEP') {
  114. tapStartSleep(null)
  115. }
  116. else {
  117. tapEndFast(null)
  118. }
  119. }
  120. if (props.record.scenario.name == 'FAST') {
  121. return
  122. }
  123. if (category_id == 'REMINDER_FS_START_FAST_T3') {
  124. tapEndSleep(null)
  125. }
  126. else if (category_id == 'REMINDER_FS_START_FAST_T4') {
  127. tapEndFast(null)
  128. }
  129. else if (category_id == 'REMINDER_FS_START_SLEEP_T3') {
  130. tapEndSleep(null)
  131. }
  132. else if (category_id == 'REMINDER_FS_START_SLEEP_T4') {
  133. tapEndFast(null)
  134. }
  135. else if (category_id == 'REMINDER_FS_END_SLEEP_T4') {
  136. tapEndFast(null)
  137. }
  138. }
  139. break;
  140. case 'END_TIMER_NOW':
  141. {
  142. if (category_id == 'REMINDER_FS_END_FAST') {
  143. operateType = 'endFast'
  144. }
  145. else {
  146. operateType = 'endSleep'
  147. }
  148. global.set_time = new Date().getTime()
  149. pickerConfirm(new Date().getTime())
  150. }
  151. break;
  152. case 'PICK_EARLIER_END':
  153. {
  154. if (category_id == 'REMINDER_FS_END_FAST') {
  155. tapEndFast(null)
  156. }
  157. else {
  158. tapEndSleep(null)
  159. }
  160. }
  161. break;
  162. case 'SKIP':
  163. break;
  164. }
  165. })
  166. }
  167. }, [props.record])
  168. useEffect(() => {
  169. if (currentRecord.fast) {
  170. var fastCount = currentRecord.fast.target_end_time - currentRecord.fast.target_start_time
  171. setFastDuration(fastCount)
  172. }
  173. if (currentRecord.sleep) {
  174. var sleepCount = currentRecord.sleep.target_end_time - currentRecord.sleep.target_start_time
  175. setSleepDuration(sleepCount)
  176. }
  177. if (props.record.current_record.status == 'WAIT_FOR_START') {
  178. setExpand(false)
  179. }
  180. }, [props.record])
  181. function tapStartFast(e) {
  182. if (process.env.TARO_ENV == 'weapp') {
  183. e.stopPropagation()
  184. }
  185. if (!user.isLogin) {
  186. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
  187. return
  188. }
  189. operateType = 'startFast'
  190. global.pauseIndexTimer = true
  191. global.set_time = new Date().getTime()
  192. defaultTimestamp = new Date().getTime()
  193. min = defaultTimestamp - 1 * 24 * 3600 * 1000
  194. max = defaultTimestamp
  195. isTimeout = false
  196. setShowTimePicker(true)
  197. // showPicker()
  198. }
  199. function tapStartSleep(e) {
  200. if (process.env.TARO_ENV == 'weapp') {
  201. e.stopPropagation()
  202. }
  203. if (!user.isLogin) {
  204. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth')
  205. return
  206. }
  207. if (status != 'ONGOING1' && props.record.scenario.name == 'FAST_SLEEP') {
  208. // if (status == 'WAIT_FOR_START') {
  209. // Taro.showToast({
  210. // title: t('feature.track_time_duration.console.lock_fast_tip'),
  211. // icon: 'none'
  212. // })
  213. // }
  214. // vibrate()
  215. setMutiEvent('start_sleep')
  216. setShowMutiPicker(true);
  217. return;
  218. }
  219. operateType = 'startSleep'
  220. global.pauseIndexTimer = true
  221. global.set_time = new Date().getTime()
  222. isTimeout = false
  223. if (props.record.scenario.name == 'SLEEP') {
  224. defaultTimestamp = new Date().getTime()
  225. min = defaultTimestamp - 6 * dayMilliSeconds
  226. max = defaultTimestamp
  227. }
  228. else {
  229. //todolist
  230. var now = new Date().getTime()
  231. var last_check_time = props.record.current_record.last_real_check_time
  232. if (now - last_check_time >= dayMilliSeconds) {
  233. //ongoing1 严重超时单独处理
  234. // var schedule_start_time = props.record.current_record.sleep.target_start_time
  235. // defaultTimestamp = Math.min(now, schedule_start_time)
  236. // min = Math.max(last_check_time, schedule_start_time - 3 * dayMillionSeconds)
  237. // max = Math.min(now, schedule_start_time + 3 * dayMillionSeconds)
  238. defaultTimestamp = now
  239. min = Math.max(last_check_time, defaultTimestamp - 6 * dayMilliSeconds)
  240. max = defaultTimestamp
  241. }
  242. else {
  243. defaultTimestamp = now
  244. min = Math.max(last_check_time, defaultTimestamp - 6 * dayMilliSeconds)
  245. max = defaultTimestamp
  246. }
  247. }
  248. setShowTimePicker(true)
  249. // showPicker()
  250. }
  251. function tapEndSleep(e) {
  252. if (process.env.TARO_ENV == 'weapp') {
  253. e.stopPropagation()
  254. }
  255. if (!user.isLogin) {
  256. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth')
  257. return
  258. }
  259. if (status != 'ONGOING2' && status != 'ONGOING') {
  260. // Taro.showToast({
  261. // title: t('feature.track_time_duration.console.lock_sleep_tip'),
  262. // icon: 'none'
  263. // })
  264. // vibrate()
  265. setMutiEvent('end_sleep')
  266. setShowMutiPicker(true);
  267. return;
  268. }
  269. operateType = 'endSleep'
  270. global.pauseIndexTimer = true
  271. global.set_time = new Date().getTime()
  272. var real_start_time = props.record.current_record.sleep.real_start_time
  273. var last_check_time = props.record.current_record.last_real_check_time
  274. var now = new Date().getTime()
  275. if (now - real_start_time >= dayMilliSeconds) {
  276. //严重超时
  277. isTimeout = true
  278. // defaultTimestamp = Math.min(props.record.current_record.sleep.target_end_time, now)
  279. // min = Math.max(last_check_time, defaultTimestamp - 3 * dayMillionSeconds)
  280. // max = Math.min(now, defaultTimestamp + 3 * dayMillionSeconds)
  281. defaultTimestamp = now
  282. min = Math.max(last_check_time, defaultTimestamp - 6 * dayMilliSeconds)
  283. max = defaultTimestamp
  284. }
  285. else {
  286. isTimeout = false
  287. defaultTimestamp = now
  288. min = Math.max(last_check_time, defaultTimestamp - 6 * dayMilliSeconds)
  289. max = defaultTimestamp
  290. }
  291. setShowTimePicker(true)
  292. // if (last_check_time + 24 * 3600 * 1000 <= new Date().getTime()) {
  293. // setShowTimePicker(true)
  294. // return
  295. // }
  296. // showPicker()
  297. }
  298. function tapEndFast(e) {
  299. if (process.env.TARO_ENV == 'weapp') {
  300. e.stopPropagation()
  301. }
  302. if (!user.isLogin) {
  303. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth')
  304. return
  305. }
  306. if (status == 'WAIT_FOR_START') {
  307. // Taro.showToast({
  308. // title: t('feature.track_time_duration.console.lock_fast_tip'),
  309. // icon: 'none'
  310. // })
  311. // vibrate()
  312. setMutiEvent('end_fast')
  313. setShowMutiPicker(true);
  314. return;
  315. }
  316. if (status == 'ONGOING1') {
  317. // showAlert({
  318. // title:t('feature.heads_up.alert_title'),
  319. // content:t('feature.heads_up.ongoing1_content'),
  320. // cancelText:t('feature.heads_up.ongoing1_cancel'),
  321. // confirmText:t('feature.heads_up.ongoing1_confirm'),
  322. // showCancel:true,
  323. // cancel:()=>{
  324. // },
  325. // confirm:()=>{
  326. // tapEndFastOperate()
  327. // }
  328. // })
  329. setMutiEvent('end_fast')
  330. setShowMutiPicker(true);
  331. return
  332. }
  333. else if (status == 'ONGOING2') {
  334. setMutiEvent('end_fast')
  335. setShowMutiPicker(true);
  336. // showAlert({
  337. // title: t('feature.heads_up.alert_title'),
  338. // content: t('feature.heads_up.ongoing2_content'),
  339. // cancelText: t('feature.heads_up.ongoing2_cancel'),
  340. // confirmText: t('feature.heads_up.ongoing2_confirm'),
  341. // showCancel: true,
  342. // cancel: () => {
  343. // },
  344. // confirm: () => {
  345. // tapEndFastOperate()
  346. // }
  347. // })
  348. return
  349. }
  350. tapEndFastOperate()
  351. }
  352. function tapEndFastOperate() {
  353. operateType = 'endFast'
  354. global.pauseIndexTimer = true
  355. global.set_time = new Date().getTime()
  356. var real_start_time = props.record.current_record.fast.real_start_time
  357. var last_check_time = props.record.current_record.last_real_check_time
  358. var now = new Date().getTime()
  359. if (now - real_start_time >= dayMilliSeconds) {
  360. //严重超时
  361. isTimeout = true
  362. defaultTimestamp = now
  363. min = Math.max(last_check_time, defaultTimestamp - 6 * dayMilliSeconds)
  364. max = defaultTimestamp
  365. }
  366. else {
  367. isTimeout = false
  368. defaultTimestamp = now
  369. min = Math.max(last_check_time, defaultTimestamp - 6 * dayMilliSeconds)
  370. max = defaultTimestamp
  371. }
  372. setShowTimePicker(true)
  373. }
  374. function layoutContent() {
  375. var limit = global.set_time - 7 * 3600 * 1000 * 24;
  376. global.limit = limit
  377. if (currentRecord.last_real_check_time) {
  378. limit = currentRecord.last_real_check_time
  379. global.limit = limit
  380. //当set_time秒数<=latest_record_time秒数时,最小限制时间戳需+1分钟
  381. if (new Date(global.set_time).getSeconds() <= new Date(currentRecord.last_real_check_time).getSeconds() && global.set_time - currentRecord.last_real_check_time > 60000) {
  382. limit = limit + 60 * 1000
  383. }
  384. }
  385. var title = getTimePickerTitle(currentRecord, t, operateType == 'endFast')
  386. var color = getColor(currentRecord, operateType == 'endFast')
  387. var duration = 0
  388. if (operateType == 'startFast' && currentRecord.fast) {
  389. duration = currentRecord.fast.target_end_time - currentRecord.fast.target_start_time
  390. }
  391. if (operateType == 'startSleep' && currentRecord.sleep) {
  392. duration = currentRecord.sleep.target_end_time - currentRecord.sleep.target_start_time
  393. }
  394. var endTimestamp = 0
  395. if (operateType == 'endFast') {
  396. endTimestamp = currentRecord.fast.target_end_time
  397. }
  398. else if (operateType == 'endSleep') {
  399. endTimestamp = currentRecord.sleep.target_end_time
  400. }
  401. return <View className="modal_content">
  402. <LimitPickers ref={limitPickerRef} limit={limit} limitDay={7}
  403. themeColor={color}
  404. title={title}
  405. showEndTime={true}
  406. isFast={operateType == 'startFast' || operateType == 'endFast'}
  407. isEnd={operateType == 'endFast' || operateType == 'endSleep'}
  408. endTimestamp={endTimestamp}
  409. // showEndTime={operateType == 'startFast' || operateType == 'startSleep'}
  410. duration={duration}
  411. onCancel={hidePicker} onChange={(e) => {
  412. pickerConfirm(e)
  413. global.pauseIndexTimer = false
  414. // hidePicker()
  415. }} />
  416. </View>
  417. }
  418. function timePickerContent() {
  419. var title = getTimePickerTitle(currentRecord, t, operateType == 'endFast')
  420. var color = getColor(currentRecord, operateType == 'endFast')
  421. // var limit = props.record.current_record.last_real_check_time
  422. // var targetTime = props.record.current_record.fast.target_end_time
  423. // if (props.record.current_record.status == 'ONGOING3') {
  424. // limit = 0
  425. // targetTime = props.record.current_record.sleep.real_end_time + 60 * 1000
  426. // }
  427. var endTimestamp = 0
  428. if (operateType == 'endFast') {
  429. endTimestamp = currentRecord.fast.target_end_time
  430. }
  431. else if (operateType == 'endSleep') {
  432. endTimestamp = currentRecord.sleep.target_end_time
  433. }
  434. var duration = 0
  435. if (operateType == 'startFast' && currentRecord.fast) {
  436. duration = currentRecord.fast.target_end_time - currentRecord.fast.target_start_time
  437. }
  438. if (operateType == 'startSleep' && currentRecord.sleep) {
  439. duration = currentRecord.sleep.target_end_time - currentRecord.sleep.target_start_time
  440. }
  441. return <View className="modal_content">
  442. <ConsolePicker ref={limitPickerRef}
  443. themeColor={color}
  444. title={title}
  445. onCancel={hidePicker}
  446. min={min}
  447. max={max}
  448. current={defaultTimestamp}
  449. duration={duration}
  450. endTimestamp={endTimestamp}
  451. isFast={operateType == 'startFast' || operateType == 'endFast'}
  452. isEnd={operateType == 'endFast' || operateType == 'endSleep'}
  453. isTimeout={isTimeout}
  454. isLoading={btnDisable}
  455. onChange={(e) => {
  456. pickerConfirm(e)
  457. global.pauseIndexTimer = false
  458. }}
  459. />
  460. {/* <LimitTimeoutPickers ref={limitPickerRef} limit={limit} limitDay={7}
  461. themeColor={color}
  462. title={title}
  463. isFast={operateType == 'endFast'}
  464. endTimestamp={endTimestamp}
  465. time={operateType == 'endFast' ? new Date(targetTime).getTime() :
  466. new Date(props.record.current_record.sleep.target_end_time).getTime()
  467. }
  468. onCancel={hidePicker} onChange={(e) => {
  469. pickerConfirm(e)
  470. global.pauseIndexTimer = false
  471. }} /> */}
  472. </View>
  473. }
  474. function showPicker() {
  475. // global.scenario = 'FAST_SLEEP'
  476. if (global.testInfotimer) {
  477. return
  478. }
  479. global.pauseIndexTimer = true
  480. global.set_time = new Date().getTime()
  481. updateNodeInfo()
  482. if (!global.isDebug) {
  483. return
  484. }
  485. // global.testInfotimer = setInterval(() => {
  486. // updateNodeInfo()
  487. // }, 1000)
  488. }
  489. function updateNodeInfo() {
  490. var node = layoutContent()
  491. global.showIndexModal(true, node, null);
  492. }
  493. function hidePicker() {
  494. var node = layoutContent()
  495. global.showIndexModal(false, node, null);
  496. setShowTimePicker(false)
  497. setBtnDisable(false)
  498. global.pauseIndexTimer = false
  499. }
  500. function followWxPub() {
  501. const resource = common.resources.filter((item: any) => {
  502. return item.code == 'follow_wx_pub'
  503. })
  504. jumpPage('/pages/common/H5?title=fast16cc 关注服务号&url=' + resource[0].url)
  505. }
  506. function pickerConfirm(t1: number) {
  507. if (btnDisable) {
  508. return
  509. }
  510. setBtnDisable(true)
  511. // hidePicker()
  512. var date = new Date(t1)
  513. var setDate = new Date(global.set_time);
  514. date.setMilliseconds(setDate.getMilliseconds());
  515. date.setSeconds(setDate.getSeconds());
  516. t1 = date.getTime();
  517. switch (operateType) {
  518. case 'startFast':
  519. startFast(t1, fastDuration).then(res => {
  520. global.indexPageRefresh()
  521. setFirstEnter(false)
  522. hidePicker()
  523. setBtnDisable(false)
  524. refreshDayNight()
  525. if (process.env.TARO_ENV == 'weapp') {
  526. if (permission.wxPubFollow) {
  527. // showAlert({
  528. // title: t('feature.track_time_duration.reminders.fast_end_title'),
  529. // content:
  530. // t('feature.track_time_duration.reminders.enable_post_fast_content',
  531. // { date: TimeFormatter.dateDescription(t1 + fastDuration, true), time: TimeFormatter.timeDescription(t1 + fastDuration) }
  532. // ),
  533. // showCancel: false,
  534. // confirmText: t('feature.track_time_duration.reminders.ok')
  535. // })
  536. }
  537. else {
  538. showAlert({
  539. title: t('feature.track_time_duration.reminders.fast_end_title'),
  540. content: t('feature.track_time_duration.reminders.post_fast_content',
  541. { date: TimeFormatter.dateDescription(t1 + fastDuration, true), time: TimeFormatter.timeDescription(t1 + fastDuration) }
  542. ),
  543. showCancel: true,
  544. cancelText: t('feature.track_time_duration.reminders.later'),
  545. confirmText: t('feature.track_time_duration.reminders.open'),
  546. confirm: () => { followWxPub() }
  547. })
  548. }
  549. }
  550. else {
  551. PushNotification.checkPermissions((res) => {
  552. //允许授权
  553. if ((kIsIOS && res.authorizationStatus == 2) || (!kIsIOS && res.alert)) {
  554. getLocalPush()
  555. // showAlert({
  556. // title: t('feature.track_time_duration.reminders.fast_end_title'),
  557. // content:
  558. // t('feature.track_time_duration.reminders.enable_post_fast_content',
  559. // { date: TimeFormatter.dateDescription(t1 + fastDuration, true), time: TimeFormatter.timeDescription(t1 + fastDuration) }
  560. // ),
  561. // showCancel: false,
  562. // confirmText: t('feature.track_time_duration.reminders.ok')
  563. // })
  564. }
  565. else {
  566. showAlert({
  567. title: t('feature.track_time_duration.reminders.fast_end_title'),
  568. content: t('feature.track_time_duration.reminders.post_fast_content',
  569. { date: TimeFormatter.dateDescription(t1 + fastDuration, true), time: TimeFormatter.timeDescription(t1 + fastDuration) }
  570. ),
  571. showCancel: true,
  572. cancelText: t('feature.track_time_duration.reminders.later'),
  573. confirmText: t('feature.track_time_duration.reminders.open'),
  574. confirm: () => {
  575. // Linking.openURL('app-settings:notifications')
  576. checkNotification()
  577. }
  578. })
  579. }
  580. })
  581. }
  582. }).catch(e => {
  583. setBtnDisable(false)
  584. })
  585. break
  586. case 'startSleep':
  587. startSleep(t1, sleepDuration).then(res => {
  588. global.indexPageRefresh()
  589. setFirstEnter(false)
  590. hidePicker()
  591. setBtnDisable(false)
  592. refreshDayNight()
  593. if (process.env.TARO_ENV == 'weapp') {
  594. if (permission.wxPubFollow) {
  595. // showAlert({
  596. // title: t('feature.track_time_duration.reminders.wake_title'),
  597. // content:
  598. // t('feature.track_time_duration.reminders.enable_post_sleep_content',
  599. // { date: TimeFormatter.dateDescription(t1 + sleepDuration, true), time: TimeFormatter.timeDescription(t1 + sleepDuration) }),
  600. // showCancel: false,
  601. // confirmText: t('feature.track_time_duration.reminders.ok')
  602. // })
  603. }
  604. else {
  605. showAlert({
  606. title: t('feature.track_time_duration.reminders.wake_title'),
  607. content: t('feature.track_time_duration.reminders.post_sleep_content',
  608. { date: TimeFormatter.dateDescription(t1 + sleepDuration, true), time: TimeFormatter.timeDescription(t1 + sleepDuration) }),
  609. cancelText: t('feature.track_time_duration.reminders.later'),
  610. confirmText: t('feature.track_time_duration.reminders.open'),
  611. showCancel: true,
  612. confirm: () => { followWxPub() }
  613. })
  614. }
  615. }
  616. else {
  617. PushNotification.checkPermissions((res) => {
  618. //允许授权
  619. if ((kIsIOS && res.authorizationStatus == 2) || (!kIsIOS && res.alert)) {
  620. getLocalPush()
  621. // showAlert({
  622. // title: t('feature.track_time_duration.reminders.wake_title'),
  623. // content:
  624. // t('feature.track_time_duration.reminders.enable_post_sleep_content',
  625. // { date: TimeFormatter.dateDescription(t1 + sleepDuration, true), time: TimeFormatter.timeDescription(t1 + sleepDuration) }),
  626. // showCancel: false,
  627. // confirmText: t('feature.track_time_duration.reminders.ok')
  628. // })
  629. }
  630. else {
  631. showAlert({
  632. title: t('feature.track_time_duration.reminders.wake_title'),
  633. content: t('feature.track_time_duration.reminders.post_sleep_content',
  634. { date: TimeFormatter.dateDescription(t1 + sleepDuration, true), time: TimeFormatter.timeDescription(t1 + sleepDuration) }),
  635. cancelText: t('feature.track_time_duration.reminders.later'),
  636. confirmText: t('feature.track_time_duration.reminders.open'),
  637. showCancel: true,
  638. confirm: () => {
  639. checkNotification()
  640. // Linking.openURL('app-settings:notifications')
  641. }
  642. })
  643. }
  644. })
  645. }
  646. }).catch((e) => {
  647. setBtnDisable(false)
  648. var picker = limitPickerRef.current;
  649. (picker as any).resetPickerData()
  650. })
  651. break
  652. case 'endSleep':
  653. endSleep(t1).then(res => {
  654. getLocalPush()
  655. setBtnDisable(false)
  656. global.indexPageRefresh()
  657. setFirstEnter(false)
  658. hidePicker()
  659. global.refrehWeekly()
  660. global.refreshStreaks()
  661. refreshDayNight()
  662. if (props.record.current_record.scenario == 'SLEEP') {
  663. global.scrollToLatest()
  664. }
  665. }).catch((e) => {
  666. setBtnDisable(false)
  667. var picker = limitPickerRef.current;
  668. (picker as any).resetPickerData()
  669. })
  670. break
  671. case 'endFast':
  672. endFast(t1).then(res => {
  673. getLocalPush()
  674. setBtnDisable(false)
  675. global.indexPageRefresh()
  676. setFirstEnter(false)
  677. hidePicker()
  678. global.scrollToLatest()
  679. global.refrehWeekly()
  680. global.refreshStreaks()
  681. refreshDayNight()
  682. global.checkAccess((res as any).access)
  683. // checkAccessProvisional((res as any).access,showFastAlert)
  684. }).catch((e) => {
  685. setBtnDisable(false)
  686. var picker = limitPickerRef.current;
  687. (picker as any).resetPickerData()
  688. })
  689. break
  690. }
  691. }
  692. function refreshDayNight() {
  693. if (global.refreshNight) {
  694. global.refreshNight()
  695. }
  696. if (global.refreshDay) {
  697. global.refreshDay()
  698. }
  699. }
  700. function expandBtnText() {
  701. if (status == 'WAIT_FOR_START') {
  702. return t('feature.track_time_duration.console.next_steps')
  703. }
  704. else if (firstEnter) {
  705. return t('feature.track_time_duration.console.show_more')
  706. }
  707. return t('feature.track_time_duration.console.next_steps')
  708. }
  709. function modalContent() {
  710. global.set_time = new Date().getTime()
  711. return <Modal
  712. testInfo={null}
  713. dismiss={() => {
  714. hidePicker()
  715. // setShowTimeoutPicker(false)
  716. }}
  717. confirm={() => { }}>
  718. {
  719. timePickerContent()
  720. }
  721. </Modal>
  722. }
  723. function mutiContent() {
  724. return <Modal
  725. testInfo={null}
  726. dismiss={() => {
  727. setShowMutiPicker(false)
  728. }}
  729. confirm={() => { }}>
  730. {
  731. mutiPickerContent()
  732. }
  733. </Modal>
  734. }
  735. function mutiPickerContent() {
  736. global.set_time = new Date().getTime()
  737. return <IndexConsoleMuti status={status} event={mutiEvent} scenario={props.record.scenario.name} close={() => setShowMutiPicker(false)} />
  738. }
  739. function single() {
  740. if (props.record.scenario.name == 'FAST') {
  741. return <View style={{ marginTop: rpxToPx(0) }}>
  742. {
  743. status == 'WAIT_FOR_START' &&
  744. <View onClick={tapStartFast} className='console_btn'>
  745. <Text style={{ fontWeight: 'bold', fontSize: rpxToPx(32), color: ColorType.black }}>{t('feature.track_time_duration.common.start_fast')}</Text>
  746. </View>
  747. }
  748. {/* {
  749. status != 'WAIT_FOR_START' && <View className='btn_line' />
  750. } */}
  751. {
  752. status == 'ONGOING' && <View onClick={tapEndFast} className={status == 'ONGOING' ? 'console_btn' : 'console_btn btn_disable'}>
  753. <Text style={{ fontWeight: 'bold', fontSize: rpxToPx(32), color: ColorType.black }}>{t('feature.track_time_duration.common.end_fast')}</Text>
  754. </View>
  755. }
  756. {
  757. status == 'WAIT_FOR_START' && <View>
  758. {
  759. !expand && <Text className='expand' onClick={() => { setExpand(true) }}>{expandBtnText()}</Text>
  760. }
  761. </View>
  762. }
  763. {status == 'WAIT_FOR_START' && expand && <View className='btn_line' />}
  764. {
  765. status == 'WAIT_FOR_START' && expand && <View onClick={tapEndFast} className={status == 'ONGOING3' ? 'console_btn' : 'console_btn btn_disable'}>
  766. <Text style={{ fontWeight: 'bold', fontSize: rpxToPx(32), color: ColorType.black }}>{t('feature.track_time_duration.common.end_fast')}</Text>
  767. </View>
  768. }
  769. {
  770. showTimePicker && modalContent()
  771. }
  772. {
  773. showMutiPicker && mutiContent()
  774. }
  775. </View>
  776. }
  777. else if (props.record.scenario.name == 'SLEEP') {
  778. return <View style={{ marginTop: rpxToPx(0) }}>
  779. {
  780. status == 'WAIT_FOR_START' &&
  781. <View onClick={tapStartSleep} className='console_btn btn_sleep'>
  782. <Text style={{ fontWeight: 'bold' }}>{t('feature.track_time_duration.common.start_sleep')}</Text>
  783. </View>
  784. }
  785. {/* {
  786. status != 'WAIT_FOR_START' && <View className='btn_line' />
  787. } */}
  788. {
  789. status == 'ONGOING' && <View onClick={tapEndSleep} className={status == 'ONGOING' ? 'console_btn btn_sleep' : 'console_btn btn_sleep btn_disable'}>
  790. <Text style={{ fontWeight: 'bold' }}>{t('feature.track_time_duration.common.end_sleep')}</Text>
  791. </View>
  792. }
  793. {
  794. showTimePicker && modalContent()
  795. }
  796. </View>
  797. }
  798. }
  799. function mixed() {
  800. return <View style={{ marginTop: rpxToPx(0) }}>
  801. {
  802. status == 'WAIT_FOR_START' ?
  803. <View onClick={tapStartFast} className='console_btn'>
  804. <Text style={{ fontWeight: 'bold', fontSize: rpxToPx(32), color: ColorType.black }}>{t('feature.track_time_duration.common.start_fast')}</Text>
  805. </View> :
  806. <View onClick={() => { tapStage(0) }} className='stage_btn'>
  807. <Text style={{ flex: 1, color: '#fff' }}>{t('feature.track_time_duration.stage.a')}</Text>
  808. {
  809. status == 'ONGOING1' ?
  810. <Text style={{ color: '#fff' }}>{TimeFormatter.countdown(currentRecord.fast.real_start_time)}</Text> :
  811. <Text style={{ color: '#fff' }}>{TimeFormatter.calculateTimeDifference(currentRecord.fast.real_start_time, currentRecord.sleep.real_start_time)}</Text>
  812. }
  813. </View>
  814. }
  815. <View className='btn_line' />
  816. {
  817. (status == 'WAIT_FOR_START' || status == 'ONGOING1') &&
  818. <View onClick={tapStartSleep} className={status == 'ONGOING1' ? 'console_btn btn_sleep' : 'console_btn btn_sleep btn_disable'}>
  819. {
  820. status != 'ONGOING1' && <Image className='lock' src={require('@assets/images/lock.png')} />
  821. }
  822. <Text style={{ fontWeight: 'bold', fontSize: rpxToPx(32), color: ColorType.black }}>{t('feature.track_time_duration.common.start_sleep')}</Text>
  823. </View>
  824. }
  825. {
  826. (status != 'WAIT_FOR_START' && status != 'ONGOING1') &&
  827. <View onClick={() => { tapStage(1) }} className='stage_btn'>
  828. <Text style={{ flex: 1, color: '#fff' }}>{t('feature.track_time_duration.stage.b')}</Text>
  829. {
  830. status == 'ONGOING2' ? <Text style={{ color: '#fff' }}>{TimeFormatter.countdown(currentRecord.sleep.real_start_time)}</Text> :
  831. <Text style={{ color: '#fff' }}>{TimeFormatter.calculateTimeDifference(currentRecord.sleep.real_start_time, currentRecord.sleep.real_end_time)}</Text>
  832. }
  833. </View>
  834. }
  835. {(expand || (status != 'WAIT_FOR_START' && status != 'ONGOING1')) && <View className='btn_line' />}
  836. {
  837. (expand || (status != 'WAIT_FOR_START' && status != 'ONGOING1')) && (status == 'WAIT_FOR_START' || status == 'ONGOING1' || status == 'ONGOING2') &&
  838. <View onClick={tapEndSleep} className={status == 'ONGOING2' ? 'console_btn btn_sleep' : 'console_btn btn_sleep btn_disable'}>
  839. {
  840. status != 'ONGOING2' && <Image className='lock' src={require('@assets/images/lock.png')} />
  841. }
  842. <Text style={{ fontWeight: 'bold', fontSize: rpxToPx(32), color: ColorType.black }}>{t('feature.track_time_duration.common.end_sleep')}</Text>
  843. </View>
  844. }
  845. {
  846. status == 'ONGOING3' &&
  847. <View onClick={() => { tapStage(2) }} className='stage_btn'>
  848. <Text style={{ flex: 1, color: '#fff' }}>{t('feature.track_time_duration.stage.c')}</Text>
  849. <Text style={{ color: '#fff' }}>{TimeFormatter.countdown(currentRecord.sleep.real_end_time)}</Text>
  850. </View>
  851. }
  852. {(expand || status == 'ONGOING3' || status == 'ONGOING') && <View className='btn_line' />}
  853. {
  854. (expand || status == 'ONGOING3' || status == 'ONGOING') &&
  855. <View onClick={tapEndFast} className={status == 'ONGOING3' ? 'console_btn' : 'console_btn btn_disable'}>
  856. {
  857. status == 'WAIT_FOR_START' && <Image className='lock' src={require('@assets/images/lock.png')} />
  858. }
  859. <Text style={{ fontWeight: 'bold', fontSize: rpxToPx(32), color: ColorType.black }}>{t('feature.track_time_duration.common.end_fast')}</Text>
  860. </View>
  861. }
  862. {
  863. (status == 'WAIT_FOR_START' || status == 'ONGOING1' || status == 'ONGOING2') &&
  864. <View>
  865. {
  866. !expand && <Text className='expand' onClick={() => { setExpand(true) }}>{expandBtnText()}</Text>
  867. }
  868. </View>
  869. }
  870. {
  871. showTimePicker && modalContent()
  872. }
  873. {
  874. showStageModal && stageContent()
  875. }
  876. {
  877. showMutiPicker && mutiContent()
  878. }
  879. </View>
  880. }
  881. function stageContent() {
  882. return <Modal
  883. testInfo={null}
  884. dismiss={() => {
  885. global.pauseIndexTimer = false
  886. setShowStageModal(false)
  887. }}
  888. confirm={() => { }}>
  889. {
  890. <CircadianDetailPopup
  891. record={currentRecord}
  892. schedule={props.record.scenario.schedule}
  893. stageIndex={stageIndex}
  894. onlyStage={true}
  895. onClose={() => { setShowStageModal(false); }} />
  896. }
  897. </Modal>
  898. }
  899. function tapStage(index) {
  900. stageIndex = index
  901. setShowStageModal(true)
  902. }
  903. return <View>
  904. {
  905. props.record.scenario.name == 'FAST_SLEEP' ? mixed() : single()
  906. }
  907. <CheckAccess record={props.record} count={props.count} access={props.access} />
  908. </View>
  909. }