ClockMain.tsx 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016
  1. import { View, Text, Image, ScrollView, PageContainer, Swiper, SwiperItem, Switch } from "@tarojs/components";
  2. import Tabbar from "@/components/navigation/TabBar";
  3. import IndexItem from '@/features/trackTimeDuration/components/IndexItem';
  4. import Rings from "@/features/trackTimeDuration/components/Rings";
  5. import './Clock.scss'
  6. import { useDispatch, useSelector } from "react-redux";
  7. import { useDidHide, useDidShow, usePageScroll, useReady, useShareAppMessage } from "@tarojs/taro";
  8. import Taro from "@tarojs/taro";
  9. import { getInfoSuccess } from "@/store/user";
  10. import { clockHome, clockSummaryRecords, clockSummaryStats, getClockRecords, getClocks, getPlans } from "@/services/trackTimeDuration";
  11. import { updateScenario } from "@/store/time";
  12. import { setConfigs } from "@/store/common";
  13. import { setScenario, setStep } from "@/store/scenario";
  14. import { useEffect, useRef, useState } from "react";
  15. import { IconPlus, IconRadioCheck, IconRadioCross } from "@/components/basic/Icons";
  16. import { ColorType } from "@/context/themes/color";
  17. import { bigRingRadius, getBgRing, getCommon, getDot, getSchedule, ringWidth, smallRingRadius } from "@/features/trackTimeDuration/hooks/RingData";
  18. import { RealRing, CurrentDot } from "@/features/trackTimeDuration/components/Rings";
  19. import IndexConsole from "@/features/trackTimeDuration/components/IndexConsole";
  20. import Modal from '@/components/layout/Modal.weapp'
  21. import { compareVersion, getTimezone, getTimezoneId, getTimezoneName, kIsIOS, rpxToPx } from "@/utils/tools";
  22. import RecordFastSleep from "@/features/trackTimeDuration/components/RecordFastSleep";
  23. import WeekCalendar from "@/features/trackTimeDuration/components/WeekCalendar";
  24. import { useTranslation } from "react-i18next";
  25. import { jumpPage } from "@/features/trackTimeDuration/hooks/Common";
  26. import Layout from "@/components/layout/layout";
  27. import { ModalType, NaviBarTitleShowType, TemplateType } from "@/utils/types";
  28. import ClockHeader from "@/features/trackTimeDuration/components/ClockHeader";
  29. import DurationPicker from "@/features/trackTimeDuration/components/DurationPicker";
  30. import SegmentPop from "@/features/trackTimeDuration/components/SegmentPop";
  31. import Box from "@/components/layout/Box";
  32. import DayNightCard from "@/features/daynight/DayNightCard";
  33. import StageSelector from "@/features/trackTimeDuration/components/StageSelector";
  34. import { ChooseScenarioBtn } from "@/features/common/SpecBtns";
  35. import { clearNightStore, showNight } from "@/store/night";
  36. import { showDay } from "@/store/day";
  37. import { clientInfo, staticResources, systemVersion } from "@/services/common";
  38. import { changeFastDuration, changeSleepDuration, setCurrentRecord, setSchedule } from "@/store/ring";
  39. import { checkAuthorized } from "@/utils/check_authorized";
  40. import { AtActivityIndicator } from "taro-ui";
  41. import Tooltip from "@/components/view/Tooltip";
  42. import AllRings from "@/features/daynight/AllRings";
  43. import Streaks from "@/features/trackTimeDuration/components/Streaks";
  44. import dayjs from 'dayjs'
  45. import DayNightSwiper from "@/features/daynight/DayNightSwiper";
  46. import showAlert from "@/components/basic/Alert";
  47. import { APP_VERSION, WX_VERSION } from "@/services/http/api";
  48. import { wxPubFollow } from "@/services/permission";
  49. import { repeat } from "lodash";
  50. import { setWXFollow } from "@/store/permission";
  51. import Discovery from "@/features/trackTimeDuration/components/Discovery";
  52. import NoData from "@/components/view/NoData";
  53. import { getLocalPush } from "@/features/trackTimeDuration/actions/TrackTimeActions";
  54. import { TimeFormatter } from "@/utils/time_format";
  55. import { userAccess } from "@/services/user";
  56. import { setAccessData } from "@/store/access";
  57. const utc = require('dayjs/plugin/utc')
  58. const timezone = require('dayjs/plugin/timezone')
  59. dayjs.extend(utc)
  60. dayjs.extend(timezone)
  61. let GradientText
  62. let useNavigation;
  63. let timer
  64. let pauseTimer = false;
  65. let AppState;
  66. let needScroll = false;
  67. let showUpdate = false;
  68. let Linking;
  69. let PushNotification;
  70. let checkNotification, uploadPermissions, NativeAppEventEmitter;
  71. let messaging;
  72. if (process.env.TARO_ENV == 'rn') {
  73. messaging = require('@react-native-firebase/messaging').default
  74. PushNotification = require('react-native-push-notification')
  75. Linking = require('react-native').Linking;
  76. AppState = require("react-native").AppState
  77. NativeAppEventEmitter = require("react-native").NativeAppEventEmitter
  78. GradientText = require('@/components/basic/GradientText').default
  79. useNavigation = require("@react-navigation/native").useNavigation
  80. checkNotification = require('@/utils/native_permission_check').checkNotification;
  81. uploadPermissions = require('@/utils/native_permission_check').uploadPermissions;
  82. }
  83. const defaultValue = `[{"scenario":{"name":"FAST_SLEEP","count":0,"schedule":{"fast":{"start_time":"15:00","end_time":"08:00"},"sleep":{"start_time":"22:00","end_time":"07:00"}}},"current_record":{"scenario":"FAST_SLEEP","status":"WAIT_FOR_START","fast":{"status":"WAIT_FOR_START","target_start_time":1710514800000,"target_end_time":1710576000000},"sleep":{"status":"WAIT_FOR_START","target_start_time":1710540000000,"target_end_time":1710572400000}},"wx_pub_followed":false,"time_input_schema":{"min":60,"max":1380,"step":5},"theme_color":{"fast":"#00FFFF","sleep":"#8183FF"}},{"scenarios":[{"name":"FAST","count":0,"schedule":{"fast":{"start_time":"15:00","end_time":"08:00"}}},{"name":"SLEEP","count":0,"schedule":{"sleep":{"start_time":"22:00","end_time":"07:00"}}},{"name":"FAST_SLEEP","count":0,"schedule":{"fast":{"start_time":"15:00","end_time":"08:00"},"sleep":{"start_time":"22:00","end_time":"07:00"}}}],"select_count":0,"theme_color":{"fast":"#00FFFF","sleep":"#8183FF"}}]`
  84. let fcmUnsubscribe: any = null;
  85. export default function Page() {
  86. const dispatch = useDispatch();
  87. global.dispatch = dispatch;
  88. let navigation;
  89. if (useNavigation) {
  90. navigation = useNavigation()
  91. }
  92. const { t } = useTranslation()
  93. const user = useSelector((state: any) => state.user);
  94. const time = useSelector((state: any) => state.time);
  95. const [count, setCount] = useState(0)
  96. const [homeData, setHomeData] = useState(null)
  97. const [loaded, setLoaded] = useState(false)
  98. const [showErrorPage, setErrorPage] = useState(false)
  99. const [showModal, setShowModal] = useState(false)
  100. const [modalDetail, setModalDetail] = useState<any>(null)
  101. const [showModal2, setShowModal2] = useState(false)
  102. const [modalDetail2, setModalDetail2] = useState<any>(null)
  103. const [debugInfo, setDebugInfo] = useState(null)
  104. const [needShowAddTip, setNeedShowAddTip] = useState(false)
  105. const [showTip, setShowTip] = useState(false)
  106. const [records, setRecords] = useState([])
  107. const [showEatCalendar, setShowEatCalendar] = useState(false)
  108. const [schedules, setSchedules] = useState<any>(null)
  109. const permission = useSelector((state: any) => state.permission);
  110. const common = useSelector((state: any) => state.common);
  111. const [access, setAccess] = useState<any>(null)
  112. const [buildVersion, setBuildVersion] = useState('')
  113. const scrollRef = useRef(null);
  114. const nightStore = useSelector((state: any) => state.night);
  115. if (process.env.TARO_ENV == 'weapp') {
  116. useShareAppMessage((e) => {
  117. return {
  118. title: t('feature.track_time_duration.common.share_title'),
  119. path: 'pages/clock/Clock'
  120. }
  121. })
  122. }
  123. useEffect(() => {
  124. console.log(new Date().toString());
  125. dispatch(staticResources() as any);
  126. pauseTimer = false;
  127. mainTimer()
  128. if (process.env.TARO_ENV == 'rn') {
  129. NativeAppEventEmitter.addListener('openNotificationSetting', (data) => {
  130. jumpPage('/pages/account/ChooseAuth', 'NotificationSetting', navigation)
  131. })
  132. }
  133. }, [])
  134. function mainTimer() {
  135. if (timer) {
  136. clearInterval(timer)
  137. timer = null
  138. }
  139. timer = setInterval(() => {
  140. var now = new Date()
  141. if (now.getDay() == 0 && now.getHours() == 12 && now.getMinutes() == 0 && now.getSeconds() == 0) {
  142. if (global.refrehWeekly) {
  143. global.refrehWeekly()
  144. }
  145. }
  146. if (global.pauseIndexTimer || pauseTimer) {
  147. return
  148. }
  149. setCount((prevCounter) => prevCounter + 1)
  150. }, 1000)
  151. }
  152. useEffect(() => {
  153. if (process.env.TARO_ENV == 'rn') {
  154. AppState.addEventListener('change', handleAppStateChange);
  155. }
  156. }, [])
  157. useEffect(() => {
  158. getCheckData()
  159. if (user.isLogin) {
  160. uploadUserClient();
  161. checkAuthorized();
  162. //检查用户是否添加过小程序
  163. checkAddToMini();
  164. wxPubFollow({ force_refresh: true }).then(res => {
  165. dispatch(setWXFollow((res as any).wx_pub_followed));
  166. })
  167. if (process.env.TARO_ENV == 'rn') {
  168. if (kIsIOS) {
  169. var Jto = require('react-native').NativeModules.NativeBridge;
  170. Jto.getNotificationAuthStatus()
  171. // Jto.rnPageLoaded()
  172. NativeAppEventEmitter.addListener('notificationResult', (data) => {
  173. console.log('notification auth result', data)
  174. global.notification = data;
  175. uploadPermissions()
  176. })
  177. }
  178. // uploadPermissions()
  179. // JPush.isNotificationEnabled((res) => {
  180. // if (res) {
  181. // const test = require('@/utils/push').default
  182. // test()
  183. // }
  184. // })
  185. checkVersionUpdate()
  186. }
  187. }
  188. else {
  189. dispatch(clearNightStore());
  190. }
  191. }, [user.isLogin])
  192. useReady(async () => {
  193. const userData = await getStorage('userData');
  194. if (userData) {
  195. dispatch(getInfoSuccess(JSON.parse(userData as string)) as any);
  196. getHistory()
  197. }
  198. })
  199. async function checkVersionUpdate() {
  200. if (!user.isLogin) {
  201. return
  202. }
  203. if (process.env.TARO_ENV == 'rn') {
  204. systemVersion().then(res => {
  205. if ((res as any).result == 'UPDATE' && !showUpdate) {
  206. showUpdate = true
  207. showAlert({
  208. title: (res as any).title,
  209. content: (res as any).description,
  210. showCancel: true,
  211. confirmText: 'Update',
  212. confirm: () => {
  213. Linking.openURL((res as any).download_url)
  214. }
  215. })
  216. }
  217. else if ((res as any).result == 'FORCE_UPDATE') {
  218. showAlert({
  219. title: (res as any).title,
  220. content: (res as any).description,
  221. showCancel: false,
  222. confirmText: 'Update',
  223. confirm: () => {
  224. Linking.openURL((res as any).download_url)
  225. }
  226. })
  227. }
  228. })
  229. return;
  230. }
  231. const showAlert1 = await getStorage('121alert') || false;
  232. if (!showAlert1) {
  233. showAlert({
  234. title: '重要更新提示',
  235. content: '🔥 连续打卡天数现根据结束日期统计;\n 🪐 断食与睡眠升级为高级功能。\n连续打卡的老用户仍可继续使用。\n更多高级功能如『进食窗口』显示、『社区排行』等敬请期待!',
  236. showCancel: false,
  237. confirmText: '我知道了'
  238. })
  239. }
  240. Taro.setStorage({ key: '121alert', data: true })
  241. }
  242. function checkAddToMini() {
  243. if (process.env.TARO_ENV == 'weapp') {
  244. const version = Taro.getAppBaseInfo().SDKVersion
  245. if (compareVersion(version, '2.30.3') >= 0) {
  246. wx.checkIsAddedToMyMiniProgram({
  247. success: (res) => {
  248. if (!res.added) {
  249. setNeedShowAddTip(true)
  250. }
  251. },
  252. fail: (e) => {
  253. }
  254. });
  255. }
  256. }
  257. }
  258. useDidShow(() => {
  259. if (process.env.TARO_ENV == 'weapp') {
  260. checkTimeZone()
  261. }
  262. else {
  263. if (!kIsIOS) {
  264. updateNotificationStatus()
  265. }
  266. }
  267. setCount(pre => pre + 1)
  268. //resume timer
  269. pauseTimer = false
  270. if (user.isLogin) {
  271. if (global.refreshRecent) {
  272. global.refreshRecent()
  273. }
  274. }
  275. setTimeout(() => {
  276. checkVersionUpdate();
  277. updateNotificationStatus();
  278. }, 1000)
  279. })
  280. usePageScroll((e) => {
  281. if (e.scrollTop > 70) {
  282. setShowTip(true)
  283. }
  284. else {
  285. setShowTip(false)
  286. }
  287. })
  288. useDidHide(() => {
  289. //pause timer
  290. pauseTimer = true
  291. })
  292. global.refreshIndex = () => {
  293. setCount((prevCounter) => prevCounter + 1)
  294. }
  295. const handleAppStateChange = (nextAppState) => {
  296. console.log(nextAppState)
  297. if (nextAppState != 'active') {
  298. return
  299. }
  300. if (nextAppState == 'active') {
  301. checkTimeZone()
  302. updateNotificationStatus()
  303. mainTimer()
  304. }
  305. };
  306. function updateNotificationStatus() {
  307. if (process.env.TARO_ENV == 'rn') {
  308. if (user.isLogin) {
  309. if (kIsIOS) {
  310. var Jto = require('react-native').NativeModules.NativeBridge;
  311. Jto.getNotificationAuthStatus()
  312. }
  313. else {
  314. uploadPermissions()
  315. }
  316. }
  317. // JPush.setBadge({
  318. // badge: 0,
  319. // appBadge: 0
  320. // })
  321. }
  322. }
  323. function checkTimeZone() {
  324. getLocalPush()
  325. setCount((prevCounter) => prevCounter + 1)
  326. var timeZoneFormatted = getTimezone()
  327. Taro.getStorage({
  328. key: 'last_tz',
  329. success: function (res) {
  330. if (res.data && res.data != timeZoneFormatted) {
  331. if (global.refrehWeekly) {
  332. global.refrehWeekly()
  333. }
  334. global.indexPageRefresh()
  335. // if (global.refreshNight){
  336. // global.refreshNight()
  337. // }
  338. // if (global.refreshDay){
  339. // global.refreshDay()
  340. // }
  341. // if (global.currentStatus != 'WAIT_FOR_START') {
  342. showAlert({
  343. title: t('feature.track_time_duration.change_tz_alert.title'),
  344. content: t('feature.track_time_duration.change_tz_alert.content', { tz: timeZoneFormatted }),
  345. showCancel: false,
  346. confirmText: t('feature.track_time_duration.change_tz_alert.confirm'),
  347. })
  348. // }
  349. }
  350. },
  351. complete: function () {
  352. Taro.setStorage({ key: 'last_tz', data: timeZoneFormatted })
  353. }
  354. })
  355. }
  356. function uploadUserClient() {
  357. var systemInfo = Taro.getSystemInfoSync();
  358. console.log(systemInfo)
  359. var language: any = systemInfo.language
  360. if (process.env.TARO_ENV == 'rn') {
  361. var NativeModules = require('react-native').NativeModules;
  362. var DeviceInfo = require('react-native-device-info').default
  363. console.log('jslfspodgfsdfopgs', DeviceInfo.getBuildNumber())
  364. setBuildVersion(DeviceInfo.getBuildNumber())
  365. if (kIsIOS) {
  366. // language = NativeModules.SettingsManager.settings.AppleLocale
  367. // languageList = NativeModules.SettingsManager.settings.AppleLanguages
  368. language = {
  369. AppleLocale: NativeModules.SettingsManager.settings.AppleLocale,
  370. AppleLanguages: NativeModules.SettingsManager.settings.AppleLanguages,
  371. NSLanguages: NativeModules.SettingsManager.settings.NSLanguages
  372. }
  373. }
  374. else {
  375. language = NativeModules.I18nManager.localeIdentifier
  376. }
  377. // iOS:
  378. // var locale = NativeModules.SettingsManager.settings.AppleLocale ||
  379. // NativeModules.SettingsManager.settings.AppleLanguages[0] // "fr_FR"
  380. // showAlert({
  381. // title: 'locale',
  382. // content: JSON.stringify(NativeModules.SettingsManager.settings)
  383. // })
  384. // Android:
  385. // locale = NativeModules.I18nManager.localeIdentifier // "fr_FR"
  386. }
  387. var timeZoneFormatted = getTimezone()
  388. var timeZoneId = ''
  389. var timeZoneName = ''
  390. if (kIsIOS) {
  391. timeZoneId = getTimezoneId()
  392. timeZoneName = getTimezoneName()
  393. }
  394. else {
  395. timeZoneId = getTimezoneId()
  396. timeZoneName = getTimezoneName()
  397. }
  398. var clientInfoParams = {
  399. client: {
  400. client_type: process.env.TARO_ENV == 'weapp' ? 'MP' : 'APP',
  401. client_version: process.env.TARO_ENV == 'weapp' ? WX_VERSION : APP_VERSION,//Taro.getAccountInfoSync().miniProgram.version : '1.0',//'1.0'
  402. wx_version: process.env.TARO_ENV == 'weapp' ? systemInfo.version : '_'
  403. },
  404. meta: {
  405. language: language,
  406. timezone: {
  407. gmt: timeZoneFormatted,
  408. id: timeZoneId,
  409. name: timeZoneName
  410. },
  411. },
  412. device: {
  413. brand: systemInfo.brand,
  414. model: systemInfo.model,
  415. platform: systemInfo.platform,
  416. system: systemInfo.system
  417. },
  418. }
  419. if (process.env.TARO_ENV == 'weapp') {
  420. (clientInfoParams as any).perm = {
  421. wxmp: {
  422. wifi_enabled: systemInfo.wifiEnabled,
  423. location_authorized: systemInfo.locationAuthorized,
  424. location_enabled: systemInfo.locationEnabled
  425. }
  426. }
  427. }
  428. clientInfo(clientInfoParams)
  429. }
  430. function getCheckData() {
  431. Promise.all([getClocks(), getPlans()]).then((list) => {
  432. setErrorPage(false)
  433. setCheckData(list)
  434. if (needScroll) {
  435. needScroll = false
  436. if (process.env.TARO_ENV == 'weapp') {
  437. setTimeout(() => {
  438. Taro.createSelectorQuery().select('#latest').boundingClientRect((rect) => {
  439. Taro.pageScrollTo({
  440. scrollTop: (rect as any).top,
  441. duration: 150
  442. })
  443. }).exec()
  444. }, 100)
  445. }
  446. else {
  447. // (scrollRef.current as any).scrollTo({ y: rpxToPx(400), animated: true })
  448. }
  449. }
  450. if (process.env.TARO_ENV == 'rn' && user.isLogin) {
  451. if (kIsIOS) {
  452. var Jto = require('react-native').NativeModules.NativeBridge;
  453. Jto.rnPageLoaded()
  454. }
  455. else {
  456. var Jto = require('react-native').NativeModules.NativeBridge;
  457. Jto.rnPageLoaded()
  458. }
  459. }
  460. setLoaded(true)
  461. }).catch((e) => {
  462. setErrorPage(true)
  463. var list = JSON.parse(defaultValue)
  464. setCheckData(list)
  465. needScroll = false
  466. setLoaded(true)
  467. })
  468. if (user.isLogin) {
  469. getHistory()
  470. userAccess().then(res => {
  471. dispatch(setAccessData(res))
  472. setAccess(res)
  473. })
  474. }
  475. }
  476. global.refreshAccess = (res) => {
  477. setAccess(res)
  478. }
  479. function setCheckData(list: any) {
  480. setHomeData(list[0])
  481. setSchedules(list[1].scenarios)
  482. global.homeData = list[0]
  483. global.currentStatus = list[0].current_record.status;
  484. var array = list[1].scenarios
  485. var schedule: any = null
  486. array.map(item => {
  487. if (item.name == 'FAST_SLEEP') {
  488. schedule = item.schedule;
  489. schedule.sleep.prev_input = item.prev_input;
  490. schedule.sleep.valid = item.valid;
  491. }
  492. })
  493. if (user.isLogin) {
  494. dispatch(updateScenario(list[0].current_record))
  495. dispatch(setConfigs(list[0].time_input_schema));
  496. dispatch(setScenario(list[0].scenario));
  497. global.scenario = list[0].scenario.name;
  498. }
  499. dispatch(setCurrentRecord(list[0].current_record))
  500. dispatch(setSchedule(schedule))
  501. // setLoaded(true)
  502. }
  503. function getHistory() {
  504. if (user.isLogin)
  505. getClockRecords({
  506. page: 1,
  507. limit: 1,
  508. // part_completed: true
  509. completed: true
  510. }).then(res => {
  511. setRecords((res as any).data)
  512. })
  513. }
  514. global.indexPageRefresh = () => {
  515. if (global.refreshStreaks) {
  516. global.refreshStreaks()
  517. }
  518. getCheckData()
  519. if (global.swiperDayNightRefresh) {
  520. global.swiperDayNightRefresh()
  521. }
  522. if (global.refrehWeekly) {
  523. global.refrehWeekly()
  524. }
  525. }
  526. global.showIndexModal = (isShow: boolean, detail: any, debugNode?: any) => {
  527. global.showModal = isShow
  528. setDebugInfo(debugNode)
  529. setShowModal(isShow)
  530. setModalDetail(detail)
  531. }
  532. global.showIndexModal2 = (isShow: boolean, detail: any) => {
  533. setDebugInfo(null)
  534. global.showModal = isShow
  535. setShowModal2(isShow)
  536. setModalDetail2(detail)
  537. }
  538. global.changeTargetDuration = (duration: number, isFast: boolean) => {
  539. var obj = JSON.parse(JSON.stringify(homeData))
  540. var record = obj.current_record
  541. if (isFast) {
  542. record.fast.target_end_time = record.fast.target_start_time + duration * 60 * 1000
  543. }
  544. else {
  545. record.sleep.target_end_time = record.sleep.target_start_time + duration * 60 * 1000
  546. }
  547. setHomeData(obj)
  548. }
  549. global.updateFastSleepData = (data: any, schedule?: any) => {
  550. if (data.id == (homeData as any).current_record.id) {
  551. var obj = JSON.parse(JSON.stringify(homeData))
  552. obj.current_record = data
  553. if (schedule) {
  554. obj.scenario.schedule = schedule
  555. }
  556. setHomeData(obj)
  557. }
  558. switch (data.scenario) {
  559. case 'FAST':
  560. if (data.status == 'WAIT_FOR_START') {
  561. dispatch(changeFastDuration(data.fast.target_end_time - data.fast.target_start_time))
  562. }
  563. break;
  564. case 'SLEEP':
  565. if (data.status == 'WAIT_FOR_START') {
  566. dispatch(changeSleepDuration(data.sleep.target_end_time - data.sleep.target_start_time))
  567. }
  568. break;
  569. case 'FAST_SLEEP':
  570. if (data.status == 'WAIT_FOR_START') {
  571. dispatch(changeFastDuration(data.fast.target_end_time - data.fast.target_start_time))
  572. }
  573. else if (data.status == 'ONGOING1') {
  574. dispatch(changeSleepDuration(data.sleep.target_end_time - data.sleep.target_start_time))
  575. }
  576. break;
  577. }
  578. }
  579. global.popScheduleAlert = (scenario, startTime) => {
  580. if (process.env.TARO_ENV == 'weapp') {
  581. if (permission.wxPubFollow) {
  582. }
  583. else {
  584. showAlert({
  585. title: t('feature.track_time_duration.reminders.schedule_title'),
  586. content: scenario.name == 'FAST' ?
  587. t('feature.track_time_duration.reminders.schedule_fast_content', { time: startTime }) :
  588. t('feature.track_time_duration.reminders.schedule_sleep_content', { time: startTime }),
  589. cancelText: t('feature.track_time_duration.reminders.later'),
  590. confirmText: t('feature.track_time_duration.reminders.open'),
  591. showCancel: true,
  592. confirm: () => {
  593. followWxPub()
  594. }
  595. })
  596. }
  597. }
  598. else {
  599. PushNotification.checkPermissions((res) => {
  600. //允许授权
  601. if ((kIsIOS && res.authorizationStatus == 2) || (!kIsIOS && res.alert)) {
  602. }
  603. else {
  604. showAlert({
  605. title: t('feature.track_time_duration.reminders.schedule_title'),
  606. content: scenario.name == 'FAST' ?
  607. t('feature.track_time_duration.reminders.schedule_fast_content', { time: startTime }) :
  608. t('feature.track_time_duration.reminders.schedule_sleep_content', { time: startTime }),
  609. cancelText: t('feature.track_time_duration.reminders.later'),
  610. confirmText: t('feature.track_time_duration.reminders.open'),
  611. showCancel: true,
  612. confirm: () => {
  613. checkNotification()
  614. // Linking.openURL('app-settings:notifications')
  615. }
  616. })
  617. }
  618. })
  619. }
  620. }
  621. global.popMixScheduleAlert = (time1, time2) => {
  622. if (process.env.TARO_ENV == 'weapp') {
  623. if (permission.wxPubFollow) {
  624. }
  625. else {
  626. showAlert({
  627. title: t('feature.track_time_duration.reminders.schedule_title'),
  628. content:
  629. t('feature.track_time_duration.reminders.schedule_mix_content'),
  630. cancelText: t('feature.track_time_duration.reminders.later'),
  631. confirmText: t('feature.track_time_duration.reminders.open'),
  632. showCancel: true,
  633. confirm: () => {
  634. followWxPub()
  635. }
  636. })
  637. }
  638. }
  639. else {
  640. PushNotification.checkPermissions((res) => {
  641. //允许授权
  642. if ((kIsIOS && res.authorizationStatus == 2) || (!kIsIOS && res.alert)) {
  643. }
  644. else {
  645. showAlert({
  646. title: t('feature.track_time_duration.reminders.schedule_title'),
  647. content:
  648. t('feature.track_time_duration.reminders.schedule_mix_content'),
  649. cancelText: t('feature.track_time_duration.reminders.later'),
  650. confirmText: t('feature.track_time_duration.reminders.open'),
  651. showCancel: true,
  652. confirm: () => {
  653. checkNotification()
  654. // Linking.openURL('app-settings:notifications')
  655. }
  656. })
  657. }
  658. })
  659. }
  660. }
  661. function followWxPub() {
  662. const resource = common.resources.filter((item: any) => {
  663. return item.code == 'follow_wx_pub'
  664. })
  665. jumpPage('/pages/common/H5?title=fast16cc 关注服务号&url=' + resource[0].url)
  666. }
  667. function modalContent() {
  668. if (showModal || showModal2) {
  669. return <Modal
  670. testInfo={debugInfo}
  671. dismiss={() => {
  672. setDebugInfo(null)
  673. setShowModal(false);
  674. setShowModal2(false);
  675. global.pauseIndexTimer = false
  676. }}
  677. confirm={() => { }}>
  678. {
  679. showModal ? modalDetail : modalDetail2
  680. }
  681. </Modal>
  682. }
  683. return <View />
  684. }
  685. async function getStorage(key: string) {
  686. try {
  687. const res = await Taro.getStorage({ key });
  688. return res.data;
  689. } catch {
  690. return '';
  691. }
  692. }
  693. function more() {
  694. jumpPage('/pages/common/RecordsHistory?type=time&title=time', 'RecordsHistory', navigation, {
  695. type: 'time',
  696. title: 'time'
  697. })
  698. }
  699. function tapLogin() {
  700. if (!user.isLogin) {
  701. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
  702. }
  703. }
  704. function headerView() {
  705. return <ClockHeader homeData={homeData} />
  706. }
  707. global.scrollToLatest = () => {
  708. needScroll = true;
  709. }
  710. var timestamp = new Date().getTime()
  711. function goSetting() {
  712. if (process.env.TARO_ENV == 'weapp') {
  713. Taro.navigateTo({
  714. url: '/pages/notification/setting'
  715. })
  716. }
  717. else {
  718. jumpPage('/pages/account/ChooseAuth', 'NotificationSetting', navigation)
  719. }
  720. }
  721. function eatCalendarContent() {
  722. return <View style={{ display: 'flex', flexDirection: 'column' }}>
  723. <View className="index_section">
  724. <Text className="index_section_title">{t('feature.track_time_duration.weekly.title')}</Text>
  725. </View>
  726. <WeekCalendar isFastSleep={false} />
  727. <View className="vip_calendar" style={{ marginBottom: 40 }} onClick={() => setShowEatCalendar(false)}>
  728. <Text style={{ color: '#fff' }}>{t('feature.track_time_duration.weekly.back')}</Text>
  729. </View>
  730. </View>
  731. }
  732. function render() {
  733. var smallTitle = ''
  734. const weekday = TimeFormatter.getDayOfWeek(new Date().getDay(), true);
  735. const date = global.language == 'en' ? dayjs().format('MMMM DD') : dayjs().format('M月D日 ')
  736. smallTitle = global.language == 'en' ? (weekday + ', ' + date) : (date + weekday);
  737. if (!loaded) {
  738. return <Layout type={TemplateType.customHeader} header={headerView()} title={smallTitle} titleShowStyle={NaviBarTitleShowType.scrollToShow}>
  739. <View style={{ width: rpxToPx(750), height: rpxToPx(900), display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
  740. <AtActivityIndicator size={40} color="#fff" />
  741. {
  742. process.env.TARO_ENV == 'weapp' && <Tabbar index={0} />
  743. }
  744. </View>
  745. </Layout>
  746. }
  747. return <Layout type={TemplateType.customHeader} header={headerView()} title={smallTitle} titleShowStyle={NaviBarTitleShowType.scrollToShow}>
  748. <View className="index_container">
  749. {
  750. needShowAddTip && showTip && <Tooltip title="添加到我的小程序" closeTip={() => { setNeedShowAddTip(false) }} />
  751. }
  752. <Text className="count">{count}</Text>
  753. <Box>
  754. <View>
  755. <IndexItem type="FAST_SLEEP" data={homeData} time={timestamp} showStage={false} />
  756. {
  757. user.isLogin ? <IndexConsole record={homeData} count={count} access={access} /> : <StageSelector />
  758. }
  759. </View>
  760. </Box>
  761. {/*
  762. <Text style={{color:'#fff',fontSize:30}} onClick={goSetting}>notification setting</Text> */}
  763. {
  764. user.isLogin && records && records.length > 0 && <View className="index_section" style={{ marginTop: -rpxToPx(25 - 12), marginBottom: -rpxToPx(20) }}>
  765. <Text className="index_section_title">{t('feature.track_time_duration.record_fast_sleep.header.latest_record')}</Text>
  766. {
  767. process.env.TARO_ENV == 'weapp' && <Text className="fast_sleep_more index_more" onClick={more}>{t('feature.track_time_duration.record_fast_sleep.header.btn_show_all')}</Text>
  768. }
  769. {
  770. process.env.TARO_ENV == 'rn' && <View onClick={more}>
  771. <GradientText style={{ fontSize: rpxToPx(32), fontWeight: 'bold', color: 'black' }}>{t('feature.track_time_duration.record_fast_sleep.header.btn_show_all')}</GradientText>
  772. </View>
  773. }
  774. </View>
  775. }
  776. {
  777. user.isLogin && records && records.length == 0 && <View style={{ marginTop: -rpxToPx(25) }} />
  778. }
  779. {
  780. user.isLogin && records && records.length > 0 && <View id="latest" className="fast_sleep_item_bg">
  781. <RecordFastSleep data={records[0]} type='record' index={-20000} />
  782. </View>
  783. }
  784. {
  785. loaded && !user.isLogin && <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', marginTop: rpxToPx(36) }}>
  786. <ChooseScenarioBtn title={t('feature.auth.login.login_now')} background={ColorType.fast} onClick={tapLogin} />
  787. </View>
  788. }
  789. {
  790. showErrorPage && <NoData refresh={() => { getCheckData() }} />
  791. }
  792. {
  793. user.isLogin && <Streaks count={count} />
  794. }
  795. {
  796. user.isLogin && !showErrorPage && <View style={{ display: 'flex', flexDirection: 'column' }}>
  797. <View className="index_section">
  798. <Text className="index_section_title">{t('feature.track_time_duration.weekly.title')}</Text>
  799. </View>
  800. <WeekCalendar isFastSleep={true} />
  801. <View className="vip_calendar" onClick={() => setShowEatCalendar(true)}>
  802. {
  803. process.env.TARO_ENV == 'weapp' ? <Text className="eat_calendar_text">{t('feature.track_time_duration.weekly.show_eating_window')}</Text> :
  804. <GradientText style={{ fontSize: rpxToPx(28), color: 'black' }} colors={[ColorType.food, ColorType.activity]}>{t('feature.track_time_duration.weekly.show_eating_window')}</GradientText>
  805. }
  806. </View>
  807. </View>
  808. }
  809. {
  810. showEatCalendar && <Modal
  811. testInfo={null}
  812. dismiss={() => {
  813. setShowEatCalendar(false)
  814. }}
  815. confirm={() => { }}>
  816. {
  817. eatCalendarContent()
  818. }
  819. </Modal>
  820. }
  821. {
  822. user.isLogin && !showErrorPage && <View className="index_section" style={{ height: rpxToPx(120), marginTop: rpxToPx(40) }}>
  823. <Text className="index_main_title">{t('feature.pro.for_pro')}</Text>
  824. </View>
  825. }
  826. {
  827. user.isLogin && !showErrorPage && <View className="index_section" style={{ marginBottom: -rpxToPx(10), marginTop: -rpxToPx(40) }}>
  828. <Text className="index_section_title">{t('feature.day_night.group_title')}</Text>
  829. </View>
  830. }
  831. {
  832. user.isLogin && !showErrorPage && <DayNightSwiper count={count} schedule={schedules} homeData={homeData} />
  833. }
  834. {
  835. user.isLogin && (process.env.TARO_ENV == 'weapp') && <View className="index_section">
  836. <Text className="index_section_title">{t('page.explore.title')}</Text>
  837. </View>
  838. }
  839. {
  840. user.isLogin && (process.env.TARO_ENV == 'weapp') && <Discovery />
  841. }
  842. {
  843. modalContent()
  844. }
  845. {
  846. homeData && <SegmentPop data={homeData} />
  847. }
  848. {
  849. homeData && <DurationPicker record={(homeData as any).current_record} />
  850. }
  851. {
  852. user.isLogin && user.test_user && homeData && access && <View style={{ display: 'flex', flexDirection: 'column' }}>
  853. <Text style={{ color: '#fff', fontSize: 15 }}>member status:{access && access.member && access.member.status}</Text>
  854. {
  855. access && access.member && access.member.status == 'MEMBER' &&
  856. <Text style={{ color: '#fff', fontSize: 15 }}>会员过期时间:{access.member.type=='NON_CONSUMABLE'?'Lifelong':dayjs(access.member.expire).format('YYYY-MM-DD HH:mm:ss')}</Text>
  857. }
  858. {
  859. access && access.member && access.member.status == 'MEMBER' &&
  860. <Text style={{ color: '#fff', fontSize: 15 }}>会员过期倒计时:{access.member.type=='NON_CONSUMABLE'?'Lifelong':TimeFormatter.countdown(access.member.expire)}</Text>
  861. }
  862. <Text style={{ color: '#fff', fontSize: 15 }}>current status:{access.fast_sleep.current.qualification.status}</Text>
  863. <Text style={{ color: '#fff', fontSize: 15 }}>previous status:{access.fast_sleep.previous.qualification.status}</Text>
  864. <Text style={{ color: '#fff', fontSize: 15 }}>trigger event:{access.fast_sleep.current.qualification.trigger_event}</Text>
  865. <Text style={{ color: '#fff', fontSize: 15 }}>lost_access_total:{access.fast_sleep.current.qualification.condition.lost_access_total}</Text>
  866. <Text style={{ color: '#fff', fontSize: 15 }}>streak_fast_min_required:{access.fast_sleep.current.qualification.condition.streak_fast_min_required}</Text>
  867. {
  868. process.env.TARO_ENV == 'rn' && <Text style={{ color: '#fff', fontSize: 15 }}>App build version:{buildVersion}</Text>
  869. }
  870. </View>
  871. }
  872. {
  873. process.env.TARO_ENV == 'weapp' && <View style={{ height: 100 }} />
  874. }
  875. <Tabbar index={0} />
  876. </View>
  877. </Layout>
  878. }
  879. return render()
  880. }