IndexConsole.tsx 41 KB

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