import Box from "@/components/layout/Box"; import Header from "@/components/layout/Header"; import Modal from "@/components/layout/Modal.weapp"; import RecordItem from "@/features/common/RecordItem"; import { delRecord } from "@/services/trackTimeDuration"; import { ModalType } from "@/utils/types"; import { View, Text, Image, PageContainer } from "@tarojs/components"; import Taro, { usePageScroll } from "@tarojs/taro"; import { useEffect, useState, memo } from "react"; import TimelineFastSleep from "./TimelineFastSleep"; import { TimeFormatter } from "@/utils/time_format"; import './RecordFastSleep.scss' import { bigRingRadius, getBgRing, getCommon, getDot, getReal, getTarget, ringWidth, smallRingRadius } from "../hooks/RingData"; import Rings from "./Rings"; import Segment from "@/components/navigation/Segment"; import Stage from "./Stage"; import CenterContentTitleModal from "@/features/common/CenterContentTitleModal"; import { useTranslation } from "react-i18next"; import { ColorType } from "@/context/themes/color"; import TimelineStage from "./TimelineStage"; import { jumpPage } from "../hooks/Common"; import { RealRing, CurrentDot } from "@/features/trackTimeDuration/components/Rings"; import { getTimezone, getTimezoneId, kIsIOS, rpxToPx } from "@/utils/tools"; import { useDispatch, useSelector } from "react-redux"; import { setSelID } from "@/store/common"; import CircadianDetailPopup from "./CircadianDetailPopup"; import dayjs from 'dayjs' import '@/utils/ring_card.scss'; import showAlert from "@/components/basic/Alert"; // import { sqrt } from 'mathjs' let AppState; if (process.env.TARO_ENV == 'rn') { AppState = require("react-native").AppState } let stageCanvasId = new Date().getTime() let startX = 0 let startY = 0 const utc = require('dayjs/plugin/utc') const timezone = require('dayjs/plugin/timezone') var advanced = require("dayjs/plugin/advancedFormat") dayjs.extend(utc) dayjs.extend(timezone) dayjs.extend(advanced) // let disableDismiss = false //https://www.php.cn/faq/629819.html // export default function RecordFastSleep(props: { data: any, type: string, delSuccess?: Function, index: any }) { const RecordFastSleep = memo((props: { data: any, type: string, index: number, disableDelete?: boolean }) => { const [count, setCount] = useState(0) const [showDetailModal, setShowDetailModal] = useState(false) const [segmentIndex, setSegmentIndex] = useState(0) const [diffTimeZone, setDiffTimeZone] = useState(false) const [multiTimeZone, setMultiTimeZone] = useState(false) const [showMore, setShowMore] = useState(false) const [selIndex, setSelIndex] = useState(0) const [showMoreModal, setShowMoreModal] = useState(false) const [showDel, setShowDel] = useState(false) const [disableDismiss, setDisableDismiss] = useState(false) const { t } = useTranslation() var canvasId = props.data.id const record = props.data; const common = useSelector((state: any) => state.common); const dispatch = useDispatch(); const handleAppStateChange = (nextAppState) => { checkTimezone() }; useEffect(() => { checkTimezone() if (process.env.TARO_ENV == 'rn') { AppState.addEventListener('change', handleAppStateChange); } if (record.scenario != 'FAST_SLEEP') { setShowMore(false) setSelIndex(0) } if (props.index == -20000) { global.refreshRecent = () => { setCount((index) => index + 1) } setTimeout(() => { setCount((index) => index + 1) }, 100) } // console.log(sqrt(-4).toString()) }, [props.data]) useEffect(() => { if (common.recordSelID != props.data.id) { setShowDel(false) } }, [common.recordSelID]) function checkTimezone() { var currentTZ = getTimezone() var isDiff = false; var isMulti = false; var tempTZ = ''; if (props.data.fast) { if (props.data.fast.real_start_timezone && props.data.fast.real_start_timezone.gmt) { tempTZ = props.data.fast.real_start_timezone.gmt if (props.data.fast.real_start_timezone.gmt != currentTZ) { isDiff = true } } if (props.data.fast.real_end_timezone && props.data.fast.real_end_timezone.gmt) { if (tempTZ != props.data.fast.real_end_timezone.gmt) { isMulti = true } if (props.data.fast.real_end_timezone.gmt != currentTZ) { isDiff = true } } } if (props.data.sleep) { if (props.data.sleep.real_start_timezone && props.data.sleep.real_start_timezone.gmt) { if (tempTZ == '') { tempTZ = props.data.sleep.real_start_timezone.gmt } else if (tempTZ != props.data.sleep.real_start_timezone.gmt) { isMulti = true } if (props.data.sleep.real_start_timezone.gmt != currentTZ) { isDiff = true } } if (props.data.sleep.real_end_timezone && props.data.sleep.real_end_timezone.gmt) { if (tempTZ != props.data.sleep.real_end_timezone.gmt) { isMulti = true } if (props.data.sleep.real_end_timezone.gmt != currentTZ) { isDiff = true } } } setDiffTimeZone(isDiff) setMultiTimeZone(isMulti) } function tapDel() { showAlert({ title: t('feature.common.modal.delete_item_title'), content: t('feature.common.modal.delete_item_content'), showCancel: true, confirm: () => { del(); }, cancel: () => { setShowDel(false) } }) } function del() { var id = props.data.id delRecord(id ).then(res => { // global.refreshTime() global.refreshStreaks() global.indexPageRefresh() Taro.showToast({ title: t('page.records_history.del_success') }) dispatch(setSelID(-1)) if (global.checkAccess) { const currentStatus = (res as any).access.current.qualification.status const preStatus = (res as any).access.previous.qualification.status if (currentStatus == 'NOT_QUALIFIED' && preStatus == 'NOT_QUALIFIED'){ } else { global.checkAccess((res as any).access) } } if (global.delFastSleep) global.delFastSleep(props.data) if (global.delFastSleep2) global.delFastSleep2(props.data) // props.delSuccess && props.delSuccess(props.data) // Taro.navigateBack() }) } function subTitle(timestamp) { if (multiTimeZone) { return t('feature.common.multi_timezones') } if (diffTimeZone) { return t('feature.common.different_timezone') } return TimeFormatter.getDateAndWeek(timestamp) } function schedules() { var timestamp = props.data.first_real_check_time return } function showDetail(e) { if (showDel) { setShowDel(false); return } dispatch(setSelID(-1)) if (props.type == 'latest') { setSegmentIndex(0) global.segmentIndex = 0 setShowDetailModal(true) return; } setShowDetailModal(true) } function getDuration(obj) { if (obj.status == 'NOT_STARTED' || obj.status == 'NOT_COMPLETED') { return '' } var start = obj.real_start_time var end = obj.real_end_time if (!end) { end = (new Date()).getTime() } return TimeFormatter.durationFormate(start, end) // return TimeFormatter.calculateTimeDifference(start, end) } function getStageDuration() { var start, end; switch (selIndex) { case 0: start = record.fast.real_start_time end = record.sleep.real_start_time break case 1: start = record.sleep.real_start_time end = record.sleep.real_end_time break case 2: start = record.sleep.real_end_time end = record.fast.real_end_time break } return TimeFormatter.durationFormate(start, end) } function durationArc(start_time: number, end_time: number) { var duration = (end_time - start_time) / 1000; return duration / (24 * 3600) * 2 * Math.PI; } function bigRing() { var common = getCommon(null, true) common.radius = bigRingRadius; common.lineWidth = ringWidth; var bgRing = getBgRing() if (props.type == 'record' || props.type == 'latest') { var realRing = getReal(record, true, true) if (props.data.status == 'ONGOING3') { realRing.color = 'rgba(0,0,0,0)' } if ((props.data.scenario == 'FAST' && props.data.fast.status == "NOT_COMPLETED") || (props.data.scenario == 'SLEEP' && props.data.sleep.status == "NOT_COMPLETED")) { realRing.durationArc = 0.01 } if (props.data.scenario == 'FAST_SLEEP' && props.data.fast.status == "NOT_COMPLETED") { realRing.durationArc = 0.01 } return } else { var currentDot1 = getDot(record, true) var targetBigRing1 = getTarget(record, true) if (record.status == 'ONGOING') { var realRing1 = getReal(record, true, false) return } if (record.status == 'WAIT_FOR_START') { return } if (record.status == 'NOT_COMPLETED') { return } var realRing1 = getReal(record, true, false) return } } function bigMoreRing() { var common = getCommon(null, true) common.radius = bigRingRadius; common.lineWidth = ringWidth; var bgRing = getBgRing() var realRing = getReal(record, true, true) realRing.color = ColorType.fast + '66' var list: any = [] if (record.scenario == 'FAST_SLEEP') { if (selIndex == 0) { const realRingBig: RealRing = { color: global.fastColor ? global.fastColor : ColorType.fast, startArc: startArc(record.fast.real_start_time), durationArc: durationArc(record.fast.real_start_time, record.sleep.real_start_time) } list.push(realRingBig) } if (selIndex == 1) { const realRingBig: RealRing = { color: global.fastColor ? global.fastColor : ColorType.fast, startArc: startArc(record.sleep.real_start_time), durationArc: durationArc(record.sleep.real_start_time, record.sleep.real_end_time) } list.push(realRingBig) } if (selIndex == 2) { const realRingBig: RealRing = { color: global.fastColor ? global.fastColor : ColorType.fast, startArc: startArc(record.sleep.real_end_time), durationArc: durationArc(record.sleep.real_end_time, record.fast.real_end_time) } list.push(realRingBig) } } return } const startArc = (time: number) => { var date = new Date(time); var hour = date.getHours(); var minute = date.getMinutes(); var second = date.getSeconds(); return (hour * 3600 + minute * 60 + second) / (24 * 3600) * 2 * Math.PI - Math.PI / 2.0; } function smallRing() { if (record.scenario == 'FAST_SLEEP') { var common = getCommon(null, false) common.radius = smallRingRadius; common.lineWidth = ringWidth; var bgRing = getBgRing() var realRing = getReal(record, false, false) if (props.type == 'record' || props.type == 'latest') { var showReal = false; if (record.sleep.status == 'WAIT_FOR_END') { realRing.durationArc = durationArc(record.sleep.target_start_time, (new Date()).getTime()) showReal = true // return } else if (record.sleep.status == 'NOT_COMPLETED') { realRing.durationArc = 0.01 showReal = true // return } else if (record.sleep.status == 'COMPLETED') { realRing = getReal(record, false, true) showReal = true // return } return // if (record.sleep.status == 'WAIT_FOR_END') { // realRing.durationArc = durationArc(record.sleep.target_start_time, (new Date()).getTime()) // return // } // else if (record.sleep.status == 'NOT_COMPLETED') { // realRing.durationArc = 0.01 // return // } // else if (record.sleep.status == 'COMPLETED') { // realRing = getReal(record, false, true) // return // } // return } else { var currentDot = getDot(record, false) var targetRing = getTarget(record, false) if (record.status == 'ONGOING2') { var realRing = getReal(record, false, false) return } if (record.status == 'ONGOING3') { currentDot.color = 'rgba(0, 255, 255, 0.5)' } return } } return null } function rings() { return { bigRing() } { smallRing() } } function recordTime() { var timestamp = props.data.first_real_check_time if (props.data.first_timezone && props.data.first_timezone.gmt) { timestamp = TimeFormatter.transferTimestamp(timestamp, props.data.first_timezone.gmt) } return TimeFormatter.dateDescription(timestamp, true) } function getArrowText() { var timeZoneFormatted = getTimezone() if (multiTimeZone) { if (props.data.first_timezone && props.data.first_timezone.id) { if (kIsIOS) { if (props.data.first_timezone.id == getTimezoneId()) { return recordTime() } } else { if (props.data.first_timezone.gmt == timeZoneFormatted) { return recordTime() } } if (global.language == 'en') { return TimeFormatter.tzTimeFormateLocalTime(props.data.first_real_check_time, props.data.first_timezone.id, 'MMM D z') // return dayjs(props.data.first_real_check_time).tz(props.data.first_timezone.id).format('MMM D z') } else { return TimeFormatter.tzTimeFormateLocalTime(props.data.first_real_check_time, props.data.first_timezone.id, 'M月D日 z') // return dayjs(props.data.first_real_check_time).tz(props.data.first_timezone.id).format('M月D日 z') } } if (props.data.first_timezone.gmt == timeZoneFormatted) { return recordTime() } return recordTime() + ' ' + props.data.first_timezone.gmt // return t('feature.common.multi_timezones') } if (diffTimeZone) { if (props.data.first_timezone.id) { if (kIsIOS) { if (props.data.first_timezone.id == getTimezoneId()) { return recordTime() } } else { if (props.data.first_timezone.gmt == timeZoneFormatted) { return recordTime() } } if (global.language == 'en') { return TimeFormatter.tzTimeFormateLocalTime(props.data.first_real_check_time, props.data.first_timezone.id, 'MMM D z') // return dayjs(props.data.first_real_check_time).tz(props.data.first_timezone.id).format('MMM D z') } else { return TimeFormatter.tzTimeFormateLocalTime(props.data.first_real_check_time, props.data.first_timezone.id, 'M月D日 z') // return dayjs(props.data.first_real_check_time).tz(props.data.first_timezone.id).format('M月D日 z') } } if (props.data.first_timezone.gmt == timeZoneFormatted) { return recordTime() } return recordTime() + ' ' + props.data.first_timezone.gmt // return t('feature.common.different_timezone') } return recordTime() } function tapStage(e, index) { stageCanvasId = new Date().getTime() setSelIndex(index); // setCount(pre=>pre+1); e.stopPropagation() } function moreStage() { var common = getCommon(null, false) common.radius = smallRingRadius; common.lineWidth = ringWidth; var bgRing = getBgRing() var realRing = getReal(record, false, true) return {bigMoreRing()} { {t('feature.track_time_duration.record_fast_sleep.item.fast')} } { {getStageDuration()} } { {t('feature.track_time_duration.record_fast_sleep.item.sleep')} } { {getDuration(record.sleep)} } { tapStage(e, 0) }}> {t('feature.track_time_duration.stage.a')} { selIndex == 0 && } { tapStage(e, 1) }}> {t('feature.track_time_duration.stage.b')} { selIndex == 1 && } { tapStage(e, 2) }}> {t('feature.track_time_duration.stage.c')} { selIndex == 2 && } } function recordDetail() { var fastDuration = '' var sleepDuration = '' var showFast = false; var showSleep = false; if (record.scenario == 'FAST_SLEEP') { fastDuration = getDuration(record.fast) sleepDuration = getDuration(record.sleep) if (record.status == 'ONGOING3') { fastDuration = t('feature.common.wait_for_end') } if (record.status == 'COMPLETED' && record.fast.status == 'NOT_COMPLETED') { fastDuration = t('feature.common.not_completed') } if (record.sleep.status == "NOT_STARTED") { sleepDuration = t('feature.common.not_started') } else if (record.sleep.status == 'NOT_COMPLETED') { sleepDuration = t('feature.common.not_completed') } showFast = true showSleep = true } else if (record.scenario == 'FAST') { fastDuration = getDuration(record.fast) if (record.fast.status == 'NOT_COMPLETED') { fastDuration = t('feature.common.not_completed') } showFast = true } else { sleepDuration = getDuration(record.sleep) if (record.sleep.status == 'NOT_COMPLETED') { sleepDuration = t('feature.common.not_completed') } showSleep = true } return { rings() } { showFast && {t('feature.track_time_duration.record_fast_sleep.item.fast')} } { showFast && {fastDuration} } { showSleep && {t('feature.track_time_duration.record_fast_sleep.item.sleep')} } { showSleep && {sleepDuration} } {getArrowText()} } function touchStart(e) { if (process.env.TARO_ENV == 'rn' || props.disableDelete) { return } startX = e.touches[0].clientX startY = e.touches[0].clientY setDisableDismiss(true) // disableDismiss = true } function touchMove(e) { if (process.env.TARO_ENV == 'rn' || props.disableDelete) { return } let x = startX let y = startY let deltaX = e.touches[0].clientX - x let deltaY = e.touches[0].clientY - y if (Math.abs(deltaX) > Math.abs(deltaY)) { if (deltaX < -80) { setShowDel(true) dispatch(setSelID(props.data.id)) global.selId = props.data.id } else if (deltaX > 80) { setShowDel(false) // global.selId = -1 } } } function touchEnd(e) { if (process.env.TARO_ENV == 'rn' || props.disableDelete) { return } startX = 0 setDisableDismiss(false) } usePageScroll((e) => { if (showDel && !disableDismiss) { console.log(disableDismiss) // setShowDel(false) } }) function modalContent() { return { setShowDetailModal(false) }} confirm={() => { }}> { setShowDetailModal(false)} /> } } return {count} {recordDetail()} { process.env.TARO_ENV == 'weapp' && {t('feature.track_time_duration.record_fast_sleep.delete')} } {/* { (props.type == 'record' || props.type == 'latest') && record.scenario == 'FAST_SLEEP' && record.sleep.status == 'COMPLETED' && { e.stopPropagation() setShowMoreModal(true) }}> {showMore ? '隐藏更多' : '显示更多'} } */} { showDetailModal && modalContent() // showDetailModal && setShowDetailModal(false)} // confirm={() => { }} /> } { showMoreModal && setShowMoreModal(false)} confirm={() => { }} /> } }) export default RecordFastSleep;