import { View, Text } from "@tarojs/components"; import './MainCard.scss' import { useEffect, useRef, useState } from "react"; import Modal from "@/components/layout/Modal.weapp"; import { rpxToPx } from "@/utils/tools"; import Rings, { RingCommon, BgRing, TargetRing, CurrentDot } from "@/features/trackTimeDuration/components/Rings"; import dayjs from "dayjs"; import moment from 'moment-timezone' import { MainColorType } from "@/context/themes/color"; import { fastWindow } from "@/services/trackTimeDuration"; import { useSelector } from "react-redux"; import { jumpPage } from "../hooks/Common"; import ConsolePicker from "./ConsolePicker"; import { endFast, startFast } from "../actions/TrackTimeActions"; import formatMilliseconds from "@/utils/format_time"; let useNavigation; let Linking, PushNotification; let checkNotification; let min = 0 let max = 0 let defaultTimestamp = 0 if (process.env.TARO_ENV == 'rn') { useNavigation = require("@react-navigation/native").useNavigation Linking = require('react-native').Linking; // JPush = require('jpush-react-native').default; PushNotification = require('react-native-push-notification') checkNotification = require('@/utils/native_permission_check').checkNotification; } export default function MainFastEatCard(props: { count: any }) { const [isFastMode, setIsFastMode] = useState(true) const [showModal, setShowModal] = useState(false) const [showTimePicker, setShowTimePicker] = useState(false); const limitPickerRef = useRef(null) const [operateType, setOperateType] = useState('startFast') const [btnDisable, setBtnDisable] = useState(false) const [logEvent, setLogEvent] = useState('LOG_ONCE'); const [startScheduleTime, setStartScheduleTime] = useState('00:00') const [endScheduleTime, setEndScheduleTime] = useState('00:00') const [eatData, setEatData] = useState(null) const [fastData, setFastData] = useState(null) const [startTime, setStartTime] = useState(null) const [endTime, setEndTime] = useState(null) const [status, setStatus] = useState('upcoming') const [loaded, setLoaded] = useState(false) const user = useSelector((state: any) => state.user); let navigation; if (useNavigation) { navigation = useNavigation() } useEffect(() => { fastWindow().then(res => { setLoaded(true) const { eat_win, fast_win } = res const fast = fast_win.fast setEatData(eat_win) setFastData(fast_win) setStartScheduleTime(fast_win.fast.schedule_start_time) setEndScheduleTime(fast_win.fast.schedule_end_time) var now = new Date().getTime() if ((fast.status == 'WAIT_FOR_END' || fast.target_start_time <= now && fast.target_end_time >= now) || isCurrentTimeInRange(fast.schedule_start_time, fast.schedule_end_time)) { setIsFastMode(true) } else { setIsFastMode(false) } update(fast) }) }, [user.isLogin]) useEffect(() => { if (fastData) { update(fastData.fast) } }, [props.count]) function refresh() { fastWindow().then(res => { const { eat_win, fast_win } = res const fast = fast_win.fast setEatData(eat_win) setFastData(fast_win) setStartScheduleTime(fast_win.fast.schedule_start_time) setEndScheduleTime(fast_win.fast.schedule_end_time) }) } function update(fast) { var now = new Date().getTime() if (fast.status == 'WAIT_FOR_END') { setStatus('process') } else if ((fast.target_start_time <= now && fast.target_end_time >= now) || isCurrentTimeInRange(fast.schedule_start_time, fast.schedule_end_time)) { setStartTime(fast.schedule_start_time) setStatus('new') } else { setStatus('upcoming') } } const common: RingCommon = { useCase: 'ChooseScenario', radius: 115, lineWidth: 26, isFast: true, status: 'WAIT_FOR_START' } const bgRing: BgRing = { color: '#EAE9E9' } function scheduleRing() { var starts: any = startScheduleTime.split(':') var ends: any = endScheduleTime.split(':') const startSeconds: any = parseInt(starts[0] + '') * 60 + parseInt(starts[1] + '') const endSeconds: any = parseInt(ends[0] + '') * 60 + parseInt(ends[1] + '') const color = isFastMode ? '#9AE2FE' : '#FE810C66' const startArc = isFastMode ? startSeconds / 1440 * 2 * Math.PI - Math.PI / 2 : endSeconds / 1440 * 2 * Math.PI - Math.PI / 2 const fastCount = endSeconds - startSeconds > 0 ? endSeconds - startSeconds : endSeconds - startSeconds + 1440 const eatCount = 1440 - fastCount const durationArc = isFastMode ? fastCount / 1440 * 2 * Math.PI : eatCount / 1440 * 2 * Math.PI return { color, startArc, durationArc } } function targetRing() { if (status != 'process') { return null } var starts: any = startScheduleTime.split(':') var ends: any = endScheduleTime.split(':') const startSeconds: any = parseInt(starts[0] + '') * 60 + parseInt(starts[1] + '') const endSeconds: any = parseInt(ends[0] + '') * 60 + parseInt(ends[1] + '') const color = isFastMode ? '#9AE2FE' : '#FE810C66' var startArc = isFastMode ? startSeconds / 1440 * 2 * Math.PI - Math.PI / 2 : endSeconds / 1440 * 2 * Math.PI - Math.PI / 2 const fastCount = endSeconds - startSeconds > 0 ? endSeconds - startSeconds : endSeconds - startSeconds + 1440 const eatCount = 1440 - fastCount var durationArc = isFastMode ? fastCount / 1440 * 2 * Math.PI : eatCount / 1440 * 2 * Math.PI if (isFastMode) { var dt = new Date(fastData.fast.target_start_time) var realSeconds = dt.getHours() * 3600 + dt.getMinutes() * 60 + dt.getSeconds() startArc = realSeconds / (1440 * 60) * 2 * Math.PI - Math.PI / 2 durationArc = ((fastData.fast.target_end_time - fastData.fast.target_start_time) / 1000) / (1440 * 60) * 2 * Math.PI } return { color, startArc, durationArc, radius: isFastMode ? 90 : null, lineWidth: isFastMode ? 10 : null } } function realRing() { if (isFastMode) { if (status != 'upcoming') { var starts: any = startTime ? startTime.split(':') : startScheduleTime.split(':') const startSeconds = parseInt(starts[0] + '') * 3600 + parseInt(starts[1] + '') * 60 const color = MainColorType.fast var startArc = startSeconds / (1440 * 60) * 2 * Math.PI - Math.PI / 2 var endSeconds = new Date().getHours() * 3600 + new Date().getMinutes() * 60 + new Date().getSeconds() if (endTime) { var ends: any = endTime.split(':') endSeconds = parseInt(ends[0] + '') * 3600 + parseInt(ends[1] + '') * 60 } const fastCount = endSeconds - startSeconds > 0 ? endSeconds - startSeconds : endSeconds - startSeconds + 1440 * 60 var durationArc = fastCount / (1440 * 60) * 2 * Math.PI if (status == 'process') { var dt = new Date(fastData.fast.target_start_time) var realSeconds = dt.getHours() * 3600 + dt.getMinutes() * 60 + dt.getSeconds() startArc = realSeconds / (1440 * 60) * 2 * Math.PI - Math.PI / 2 durationArc = ((new Date().getTime() - fastData.fast.target_start_time) / 1000) / (1440 * 60) * 2 * Math.PI } return { color, startArc, durationArc, radius: status == 'process' ? 90 : null, lineWidth: status == 'process' ? 15 : null } } } else { if (isCurrentTimeInRange(endScheduleTime, startScheduleTime)) { var starts: any = endScheduleTime.split(':') const startSeconds = parseInt(starts[0] + '') * 60 + parseInt(starts[1] + '') const color = MainColorType.eat const startArc = startSeconds / 1440 * 2 * Math.PI - Math.PI / 2 var endSeconds = new Date().getHours() * 60 + new Date().getMinutes() const fastCount = endSeconds - startSeconds > 0 ? endSeconds - startSeconds : endSeconds - startSeconds + 1440 const durationArc = fastCount / 1440 * 2 * Math.PI return { color, startArc, durationArc, radius: 90, lineWidth: 10 } } } } function isCurrentTimeInRange(start, end) { // 获取当前时间 const now = new Date(); const currentTime = now.getHours() * 60 + now.getMinutes(); // 当前时间转换为分钟 // 将时间点转换为分钟 const [startHour, startMinute] = start.split(':').map(Number); const [endHour, endMinute] = end.split(':').map(Number); const startTime = startHour * 60 + startMinute; // 开始时间转换为分钟 const endTime = endHour * 60 + endMinute; // 结束时间转换为分钟 // 处理跨日的情况 if (endTime < startTime) { return currentTime >= startTime || currentTime <= endTime; } // 判断当前时间是否在范围内 return currentTime >= startTime && currentTime <= endTime; } function getTimeToDestination(timeStr, isPasted) { // 获取当前时间 const now = new Date(); const currentHours = now.getHours(); const currentMinutes = now.getMinutes(); const currentSeconds = now.getSeconds(); // 解析目标时间 const [targetHours, targetMinutes] = timeStr.split(':').map(Number); // 计算时间差 let hours = targetHours - currentHours; let minutes = targetMinutes - currentMinutes; let seconds = 60 - currentSeconds; if (minutes < 0) { minutes += 60; hours--; } if (hours < 0) { hours += 24; } if (seconds === 60) { seconds = 0; minutes++; } // 如果是过去的时间,则返回剩余时间 if (isPasted) { hours = 24 - hours; minutes = 60 - minutes; seconds = 60 - seconds; } // 格式化输出 return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`; } function ring() { var offset = 0 var hour = new Date().getHours() var minute = new Date().getMinutes() if (hour != new Date().getHours() || minute != new Date().getMinutes()) { offset = hour * 60 + minute - new Date().getHours() * 60 - new Date().getMinutes() } const currentDot: CurrentDot = { color: isFastMode ? MainColorType.fast : MainColorType.eat, lineWidth: 10, borderColor: '#fff', offset: offset, whiteIcon: true } return } function formatTime(format: string, timestamp?: number) { // var moment = require('moment-timezone'); // if (current) { // if (timestamp) { // return moment(timestamp).tz(current.time.timezone.id).format(format) // } // return moment().tz(current.time.timezone.id).format(format) // } return dayjs().format(format) } function switchMode() { setIsFastMode(!isFastMode) } function getFastStatus() { switch (status) { case 'process': return 'Process' case 'new': return 'New Open' case 'upcoming': return 'Upcoming' } return '' } function getFastTime() { var milliSeconds = 0; switch (status) { case 'process': milliSeconds = new Date().getTime() - fastData.fast.real_start_time break; case 'new': return getTimeToDestination(fastData.fast.schedule_start_time, true) case 'upcoming': return getTimeToDestination(fastData.fast.schedule_start_time, false) } var seconds = Math.floor(milliSeconds / 1000) const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const remainingSeconds = seconds % 60; return `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`; } function getEatTime() { return getTimeToDestination(eatData.schedule_start_time, isCurrentTimeInRange(eatData.schedule_start_time, eatData.schedule_end_time)) } function tapFastStart() { } function tapFastEnd() { } function tapStartLog() { if (status == 'upcoming'){ return; } if (!user.isLogin) { jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation) return } defaultTimestamp = new Date().getTime() min = defaultTimestamp - 1 * 24 * 3600 * 1000 max = defaultTimestamp setOperateType('startFast') setShowTimePicker(true) } function tapEndLog() { if (status != 'process') { return } defaultTimestamp = new Date().getTime() // defaultTimestamp = e ? new Date().getTime() : logEventTimestamp min = defaultTimestamp - 1 * 24 * 3600 * 1000 max = defaultTimestamp setOperateType('endFast') setShowTimePicker(true) } function modalContent() { global.set_time = new Date().getTime() return { setShowTimePicker(false) }} confirm={() => { }}> { timePickerContent() } } function timePickerContent() { var title = operateType == 'endFast' ? '结束断食' : '开始断食' var color = MainColorType.fast var endTimestamp = 0 if (operateType == 'endFast') { endTimestamp = fastData.fast.target_end_time } var duration = fastData.fast.target_duration return { setShowTimePicker(false) }} min={min} max={max} current={defaultTimestamp} duration={duration} endTimestamp={endTimestamp} isFast={true} isEnd={operateType == 'endFast'} isTimeout={false} isLoading={btnDisable} onChange={(e) => { pickerConfirm(e, null) global.pauseIndexTimer = false }} /> } function pickerConfirm(t1: number, event: any) { if (btnDisable) { return } global.scenario = 'FAST' setBtnDisable(true) var date = new Date(t1) var setDate = new Date(global.set_time); date.setMilliseconds(setDate.getMilliseconds()); date.setSeconds(setDate.getSeconds()); t1 = date.getTime(); if (operateType == 'startFast') { startFast(t1, fastData.fast.target_duration, event ? event : logEvent).then(res => { setBtnDisable(false) refresh() setShowTimePicker(false) }).catch(e => { setBtnDisable(false) }) } else { endFast(t1, event ? event : logEvent).then(res => { setBtnDisable(false) refresh() setShowTimePicker(false) }).catch(e => { setBtnDisable(false) }) } } if (!loaded) { return } return { setShowModal(true) }}>Fast Eat Night{props.count} { ring() } { isFastMode && {getFastStatus()} } {isFastMode ? getFastTime() : getEatTime()} {global.language == 'en' ? formatTime('dddd, MMM D') : formatTime('MMMD日 dddd')} {isFastMode?formatMilliseconds(fastData.fast.target_duration):formatMilliseconds(eatData.target_end_time-eatData.target_start_time)} { isFastMode && { status == 'process' ? Fast starts : Fast starts: {startScheduleTime} } { status == 'process' ? {dayjs(fastData.fast.target_start_time).format('HH:mm')} : Log{status == 'new' && } } Fast ends: {status == 'process' ?dayjs(fastData.fast.target_end_time).format('HH:mm'):endScheduleTime} Log } Switch { showModal && setShowModal(false)}> {props.count} } { showTimePicker && modalContent() } }