Clock.tsx 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  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'
  21. import { compareVersion, getTimezone, getTimezoneId, getTimezoneName, 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. const utc = require('dayjs/plugin/utc')
  52. const timezone = require('dayjs/plugin/timezone')
  53. dayjs.extend(utc)
  54. dayjs.extend(timezone)
  55. let GradientText
  56. let useNavigation;
  57. let timer
  58. let pauseTimer = false;
  59. let AppState;
  60. let needScroll = false;
  61. let showUpdate = false;
  62. let Linking;
  63. let JPush;
  64. let checkNotification, uploadPermissions, NativeAppEventEmitter;
  65. let messaging;
  66. let PushNotification;
  67. let Importance;
  68. if (process.env.TARO_ENV == 'rn') {
  69. messaging = require('@react-native-firebase/messaging').default
  70. JPush = require('jpush-react-native').default;
  71. Linking = require('react-native').Linking;
  72. AppState = require("react-native").AppState
  73. NativeAppEventEmitter = require("react-native").NativeAppEventEmitter
  74. GradientText = require('@/components/basic/GradientText').default
  75. useNavigation = require("@react-navigation/native").useNavigation
  76. checkNotification = require('@/utils/native_permission_check').checkNotification;
  77. uploadPermissions = require('@/utils/native_permission_check').uploadPermissions;
  78. PushNotification = require('react-native-push-notification')
  79. Importance = require('react-native-push-notification').Importance
  80. }
  81. 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"}}]`
  82. let fcmUnsubscribe: any = null;
  83. export default function Page() {
  84. const dispatch = useDispatch();
  85. global.dispatch = dispatch;
  86. let navigation;
  87. if (useNavigation) {
  88. navigation = useNavigation()
  89. }
  90. const { t } = useTranslation()
  91. const user = useSelector((state: any) => state.user);
  92. const time = useSelector((state: any) => state.time);
  93. const [count, setCount] = useState(0)
  94. const [homeData, setHomeData] = useState(null)
  95. const [loaded, setLoaded] = useState(false)
  96. const [showErrorPage, setErrorPage] = useState(false)
  97. const [showModal, setShowModal] = useState(false)
  98. const [modalDetail, setModalDetail] = useState<any>(null)
  99. const [showModal2, setShowModal2] = useState(false)
  100. const [modalDetail2, setModalDetail2] = useState<any>(null)
  101. const [debugInfo, setDebugInfo] = useState(null)
  102. const [needShowAddTip, setNeedShowAddTip] = useState(false)
  103. const [showTip, setShowTip] = useState(false)
  104. const [records, setRecords] = useState([])
  105. const permission = useSelector((state: any) => state.permission);
  106. const common = useSelector((state: any) => state.common);
  107. const scrollRef = useRef(null);
  108. const nightStore = useSelector((state: any) => state.night);
  109. if (process.env.TARO_ENV == 'weapp') {
  110. useShareAppMessage((e) => {
  111. return {
  112. title: t('feature.track_time_duration.common.share_title'),
  113. path: 'pages/clock/Clock'
  114. }
  115. })
  116. }
  117. useEffect(() => {
  118. console.log(new Date().toString());
  119. dispatch(staticResources() as any);
  120. timer = setInterval(() => {
  121. var now = new Date()
  122. if (now.getDay() == 0 && now.getHours() == 12 && now.getMinutes() == 0 && now.getSeconds() == 0) {
  123. if (global.refrehWeekly) {
  124. global.refrehWeekly()
  125. }
  126. }
  127. if (global.pauseIndexTimer || pauseTimer) {
  128. return
  129. }
  130. setCount((prevCounter) => prevCounter + 1)
  131. }, 1000)
  132. }, [])
  133. useEffect(() => {
  134. // Taro.request({
  135. // url:'https://api.fast.dev.liveplus.fun/api/static-resource-urls',
  136. // method:'GET',
  137. // data:{},
  138. // timeout:20000,
  139. // success(result) {
  140. // showAlert({
  141. // title:'success',
  142. // content:JSON.stringify(result)
  143. // })
  144. // },
  145. // fail(res) {
  146. // showAlert({
  147. // title:'fail',
  148. // content:JSON.stringify(res)
  149. // })
  150. // },
  151. // })
  152. if (process.env.TARO_ENV == 'weapp') {
  153. loadWXCache()
  154. }
  155. else {
  156. loadRNCache()
  157. // PushNotification.configure({
  158. // onRegister: function (token) {
  159. // console.log('TOKEN:', token);
  160. // },
  161. // onNotification: function (notification) {
  162. // console.log('NOTIFICATION:', notification);
  163. // // notification.finish(PushNotificationIOS.FetchResult.NoData);
  164. // },
  165. // popInitialNotification: true,
  166. // });
  167. // var channelId = "your-channel-id" + new Date().getTime()
  168. // PushNotification.createChannel({
  169. // channelId: channelId, // (required)
  170. // channelName: "My channel", // (required)
  171. // channelDescription: "A channel to categorise your notifications", // (optional) default: undefined.
  172. // playSound: false, // (optional) default: true
  173. // soundName: "default", // (optional) See `soundName` parameter of `localNotification` function
  174. // importance: Importance.HIGH, // (optional) default: Importance.HIGH. Int value of the Android notification importance
  175. // vibrate: true, // (optional) default: true. Creates the default vibration pattern if true.
  176. // }, (created) => {
  177. // console.log('create channel result',created)
  178. // PushNotification.localNotificationSchedule({
  179. // //... You can use all the options from localNotifications
  180. // channelId: channelId,
  181. // title: 'Leon test',
  182. // message: "Local notification push", // (required)
  183. // date: new Date(Date.now() + 10 * 1000), // in 60 secs
  184. // allowWhileIdle: true, // (optional) set notification to work while on doze, default: false
  185. // // repeatType:'minute',
  186. // /* Android Only Properties */
  187. // // repeatTime: 1, // (optional) Increment of configured repeatType. Check 'Repeating Notifications' section for more info.
  188. // });
  189. // })
  190. // PushNotification.localNotificationSchedule({
  191. // //... You can use all the options from localNotifications
  192. // title: 'Leon test2',
  193. // message: "Local notification push2", // (required)
  194. // date: new Date(Date.now() + 15 * 1000), // in 60 secs
  195. // allowWhileIdle: true, // (optional) set notification to work while on doze, default: false
  196. // // repeatType:'minute',
  197. // /* Android Only Properties */
  198. // // repeatTime: 1, // (optional) Increment of configured repeatType. Check 'Repeating Notifications' section for more info.
  199. // });
  200. // PushNotification.localNotificationSchedule({
  201. // //... You can use all the options from localNotifications
  202. // channelId: "your-channel-id"+new Date().getTime(),
  203. // title: 'Leon test',
  204. // message: "Local notification push", // (required)
  205. // date: new Date(Date.now() + 10 * 1000), // in 60 secs
  206. // allowWhileIdle: true, // (optional) set notification to work while on doze, default: false
  207. // // repeatType:'minute',
  208. // /* Android Only Properties */
  209. // // repeatTime: 1, // (optional) Increment of configured repeatType. Check 'Repeating Notifications' section for more info.
  210. // });
  211. // PushNotification.localNotificationSchedule({
  212. // title: "My notification title",
  213. // message: "My notification message",
  214. // date: new Date(Date.now() + 10 * 1000), // first trigger in 30 secs
  215. // // channelId: 'DemoAppID',
  216. // repeatType: 'time',
  217. // repeatTime: 30 * 1000 // repeats every 30 seconds (value has to be defined in miliseconds when the repeatType is 'time')
  218. // });
  219. }
  220. if (process.env.TARO_ENV == 'rn') {
  221. JPush.setBadge({
  222. badge: 0,
  223. appBadge: 0
  224. })
  225. JPush.isNotificationEnabled((res) => {
  226. if (res) {
  227. const test = require('@/utils/push').default
  228. test()
  229. }
  230. })
  231. AppState.addEventListener('change', handleAppStateChange);
  232. /*
  233. if (Taro.getSystemInfoSync().platform == 'ios') {
  234. setTimeout(() => {
  235. var Jto = require('react-native').NativeModules.NativeBridge;
  236. // Jto.authNotification()
  237. Jto.getNotificationAuthStatus()
  238. }, 5000)
  239. NativeAppEventEmitter.addListener('notificationResult', (data) => {
  240. console.log(data)
  241. showAlert({
  242. title:'notification status',
  243. content:data
  244. })
  245. })
  246. }*/
  247. }
  248. }, [])
  249. async function demo() {
  250. }
  251. useEffect(() => {
  252. console.log(user.isLogin)
  253. getCheckData()
  254. // global.pauseIndexTimer = !user.isLogin
  255. if (user.isLogin) {
  256. uploadUserClient();
  257. checkAuthorized();
  258. //检查用户是否添加过小程序
  259. checkAddToMini();
  260. wxPubFollow({ force_refresh: true }).then(res => {
  261. dispatch(setWXFollow((res as any).wx_pub_followed));
  262. })
  263. if (process.env.TARO_ENV == 'rn') {
  264. if (Taro.getSystemInfoSync().platform == 'ios') {
  265. var Jto = require('react-native').NativeModules.NativeBridge;
  266. Jto.getNotificationAuthStatus()
  267. Jto.rnPageLoaded()
  268. NativeAppEventEmitter.addListener('notificationResult', (data) => {
  269. console.log('notification auth result', data)
  270. global.notification = data;
  271. uploadPermissions()
  272. })
  273. NativeAppEventEmitter.addListener('notificationReceive', (data) => {
  274. console.log('notification receive action 222', data)
  275. debugger
  276. })
  277. }
  278. // uploadPermissions()
  279. JPush.isNotificationEnabled((res) => {
  280. if (res) {
  281. const test = require('@/utils/push').default
  282. test()
  283. }
  284. })
  285. checkVersionUpdate()
  286. }
  287. }
  288. else {
  289. dispatch(clearNightStore());
  290. }
  291. }, [user.isLogin])
  292. useReady(async () => {
  293. const userData = await getStorage('userData');
  294. if (userData) {
  295. dispatch(getInfoSuccess(JSON.parse(userData as string)) as any);
  296. getHistory()
  297. }
  298. })
  299. async function checkVersionUpdate() {
  300. if (!user.isLogin) {
  301. return
  302. }
  303. if (process.env.TARO_ENV == 'rn') {
  304. systemVersion().then(res => {
  305. if ((res as any).result == 'UPDATE' && !showUpdate) {
  306. showUpdate = true
  307. showAlert({
  308. title: (res as any).title,
  309. content: (res as any).description,
  310. showCancel: true,
  311. confirmText: '更新',
  312. confirm: () => {
  313. Linking.openURL((res as any).download_url)
  314. }
  315. })
  316. }
  317. else if ((res as any).result == 'FORCE_UPDATE') {
  318. showAlert({
  319. title: (res as any).title,
  320. content: (res as any).description,
  321. showCancel: false,
  322. confirmText: '更新',
  323. confirm: () => {
  324. Linking.openURL((res as any).download_url)
  325. }
  326. })
  327. }
  328. })
  329. return;
  330. }
  331. const showAlert1 = await getStorage('120alert') || false;
  332. if (!showAlert1) {
  333. showAlert({
  334. title: '版本更新提示',
  335. content: '「连续纪录」新增归零倒计时提示⏳\n别让连续记录终止, 将它们一直保持下去!',
  336. showCancel: false,
  337. confirmText: '我知道了'
  338. })
  339. }
  340. Taro.setStorage({ key: '120alert', data: true })
  341. }
  342. function checkAddToMini() {
  343. if (process.env.TARO_ENV == 'weapp') {
  344. const version = Taro.getAppBaseInfo().SDKVersion
  345. if (compareVersion(version, '2.30.3') >= 0) {
  346. wx.checkIsAddedToMyMiniProgram({
  347. success: (res) => {
  348. if (!res.added) {
  349. setNeedShowAddTip(true)
  350. }
  351. },
  352. fail: (e) => {
  353. }
  354. });
  355. }
  356. }
  357. }
  358. useDidShow(() => {
  359. checkTimeZone()
  360. setCount(pre => pre + 1)
  361. //resume timer
  362. pauseTimer = false
  363. if (user.isLogin) {
  364. if (global.refreshRecent) {
  365. global.refreshRecent()
  366. }
  367. }
  368. setTimeout(() => {
  369. checkVersionUpdate();
  370. updateNotificationStatus();
  371. }, 1000)
  372. })
  373. usePageScroll((e) => {
  374. if (e.scrollTop > 70) {
  375. setShowTip(true)
  376. }
  377. else {
  378. setShowTip(false)
  379. }
  380. })
  381. useDidHide(() => {
  382. //pause timer
  383. pauseTimer = true
  384. })
  385. global.refreshIndex = () => {
  386. setCount((prevCounter) => prevCounter + 1)
  387. }
  388. const handleAppStateChange = (nextAppState) => {
  389. console.log(nextAppState)
  390. if (nextAppState != 'active') {
  391. return
  392. }
  393. checkTimeZone()
  394. updateNotificationStatus()
  395. };
  396. function updateNotificationStatus() {
  397. if (process.env.TARO_ENV == 'rn') {
  398. if (user.isLogin) {
  399. if (Taro.getSystemInfoSync().platform == 'ios') {
  400. var Jto = require('react-native').NativeModules.NativeBridge;
  401. Jto.getNotificationAuthStatus()
  402. }
  403. }
  404. JPush.setBadge({
  405. badge: 0,
  406. appBadge: 0
  407. })
  408. }
  409. }
  410. function checkTimeZone() {
  411. setCount((prevCounter) => prevCounter + 1)
  412. var timeZoneFormatted = getTimezone()
  413. Taro.getStorage({
  414. key: 'last_tz',
  415. success: function (res) {
  416. if (res.data && res.data != timeZoneFormatted) {
  417. if (global.refrehWeekly) {
  418. global.refrehWeekly()
  419. }
  420. // if (global.refreshNight){
  421. // global.refreshNight()
  422. // }
  423. // if (global.refreshDay){
  424. // global.refreshDay()
  425. // }
  426. if (global.currentStatus != 'WAIT_FOR_START') {
  427. showAlert({
  428. title: t('feature.track_time_duration.change_tz_alert.title'),
  429. content: t('feature.track_time_duration.change_tz_alert.content', { tz: timeZoneFormatted }),
  430. showCancel: false,
  431. confirmText: t('feature.track_time_duration.change_tz_alert.confirm'),
  432. })
  433. }
  434. }
  435. },
  436. complete: function () {
  437. Taro.setStorage({ key: 'last_tz', data: timeZoneFormatted })
  438. }
  439. })
  440. }
  441. function uploadUserClient() {
  442. var systemInfo = Taro.getSystemInfoSync();
  443. console.log(systemInfo)
  444. var language: any = systemInfo.language
  445. if (process.env.TARO_ENV == 'rn') {
  446. var NativeModules = require('react-native').NativeModules;
  447. if (Taro.getSystemInfoSync().platform == 'ios') {
  448. // language = NativeModules.SettingsManager.settings.AppleLocale
  449. // languageList = NativeModules.SettingsManager.settings.AppleLanguages
  450. language = {
  451. AppleLocale: NativeModules.SettingsManager.settings.AppleLocale,
  452. AppleLanguages: NativeModules.SettingsManager.settings.AppleLanguages,
  453. NSLanguages: NativeModules.SettingsManager.settings.NSLanguages
  454. }
  455. }
  456. else {
  457. language = NativeModules.I18nManager.localeIdentifier
  458. }
  459. // iOS:
  460. // var locale = NativeModules.SettingsManager.settings.AppleLocale ||
  461. // NativeModules.SettingsManager.settings.AppleLanguages[0] // "fr_FR"
  462. // showAlert({
  463. // title: 'locale',
  464. // content: JSON.stringify(NativeModules.SettingsManager.settings)
  465. // })
  466. // Android:
  467. // locale = NativeModules.I18nManager.localeIdentifier // "fr_FR"
  468. }
  469. var timeZoneFormatted = getTimezone()
  470. var timeZoneId = ''
  471. var timeZoneName = ''
  472. if (Taro.getSystemInfoSync().platform == 'ios') {
  473. timeZoneId = getTimezoneId()
  474. timeZoneName = getTimezoneName()
  475. }
  476. clientInfo({
  477. client: {
  478. client_type: process.env.TARO_ENV == 'weapp' ? 'MP' : 'APP',
  479. client_version: process.env.TARO_ENV == 'weapp' ? WX_VERSION : APP_VERSION,//Taro.getAccountInfoSync().miniProgram.version : '1.0',//'1.0'
  480. wx_version: process.env.TARO_ENV == 'weapp' ? systemInfo.version : '_'
  481. },
  482. meta: {
  483. language: language,
  484. timezone: {
  485. gmt: timeZoneFormatted,
  486. id: timeZoneId,
  487. name: timeZoneName
  488. },
  489. },
  490. device: {
  491. brand: systemInfo.brand,
  492. model: systemInfo.model,
  493. platform: systemInfo.platform,
  494. system: systemInfo.system
  495. },
  496. perm: {
  497. wifi_enabled: systemInfo.wifiEnabled,
  498. location_authorized: systemInfo.locationAuthorized,
  499. location_enabled: systemInfo.locationEnabled
  500. }
  501. })
  502. }
  503. function loadWXCache() {
  504. var showDayRing = Taro.getStorageSync('showDayRing') || false;
  505. var showNightRing = Taro.getStorageSync('showNightRing') || false;
  506. dispatch(showDay(showDayRing))
  507. dispatch(showNight(showNightRing))
  508. var gps = Taro.getStorageSync('gps')
  509. if (gps) {
  510. global.locationDetail = JSON.parse(gps)
  511. }
  512. var userData = Taro.getStorageSync('userData')
  513. if (userData) {
  514. dispatch(getInfoSuccess(JSON.parse(userData)));
  515. }
  516. }
  517. async function loadRNCache() {
  518. var showDayRing = await getStorage('showDayRing') || false;
  519. var showNightRing = await getStorage('showNightRing') || false;
  520. dispatch(showDay(showDayRing))
  521. dispatch(showNight(showNightRing))
  522. var gps = await getStorage('gps')
  523. if (gps) {
  524. global.locationDetail = JSON.parse(gps)
  525. }
  526. var userData = await getStorage('userData')
  527. console.log(userData)
  528. if (userData) {
  529. dispatch(getInfoSuccess(JSON.parse(userData)));
  530. }
  531. // //测试直接登录
  532. // else {
  533. // userData = '{"metrics_times":0,"ongoing":false,"id":"fe6641e66a0e411937a52511e19851cd","mobile_bind":false,"mobile":"","avatar":"https://api.fast.dev.liveplus.fun/api/avatars/fast_441b5a21.svg","nickname":"fast_441b5a21","type":"GENERAL","lv":1,"invite_code":"LVQ5","input_invite_code":true,"reg_time":1712838856000,"login_bind":{"wx":false,"wx_mp":false,"wx_pub":false,"qq":false,"weibo":false},"test_user":true,"manager_user":false,"web_user":false,"rjv_balance":0,"day_level":1,"scenario_select_count":77,"push_enabled":false,"is_new_user":true,"lang":"en","timezone":{},"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdWQiOiJhY2NvdW50Iiwic3ViIjoiZmU2NjQxZTY2YTBlNDExOTM3YTUyNTExZTE5ODUxY2QiLCJpc3MiOiJmYXN0Iiwibmlja25hbWUiOiJmYXN0XzQ0MWI1YTIxIiwidHlwIjoiQmVhcmVyIiwic2Vzc2lvbl9zdGF0ZSI6IjA0NTcxOGYzN2Y5NTYzYjcxMTNkMWZhODI5NmE2MjQ2IiwiZXhwIjoxNzQ2Njg4NTYxLCJpYXQiOjE3MTUxNTI1NjF9.x1CguOILCTjT8lKcEdSEeuS9ACc5QK2G4Rxmcz9OMLQ","need_improve":false}'
  534. // dispatch(getInfoSuccess(JSON.parse(userData)));
  535. // }
  536. }
  537. function getCheckData() {
  538. Promise.all([getClocks(), getPlans()]).then((list) => {
  539. setErrorPage(false)
  540. setCheckData(list)
  541. if (needScroll) {
  542. needScroll = false
  543. if (process.env.TARO_ENV == 'weapp') {
  544. setTimeout(() => {
  545. Taro.createSelectorQuery().select('#latest').boundingClientRect((rect) => {
  546. Taro.pageScrollTo({
  547. scrollTop: (rect as any).top,
  548. duration: 150
  549. })
  550. }).exec()
  551. }, 100)
  552. }
  553. else {
  554. // debugger
  555. // (scrollRef.current as any).scrollTo({ y: rpxToPx(400), animated: true })
  556. }
  557. }
  558. setLoaded(true)
  559. }).catch((e) => {
  560. setErrorPage(true)
  561. var list = JSON.parse(defaultValue)
  562. setCheckData(list)
  563. needScroll = false
  564. setLoaded(true)
  565. })
  566. getHistory()
  567. }
  568. function setCheckData(list: any) {
  569. setHomeData(list[0])
  570. global.homeData = list[0]
  571. global.currentStatus = list[0].current_record.status;
  572. var array = list[1].scenarios
  573. var schedule: any = null
  574. array.map(item => {
  575. if (item.name == 'FAST_SLEEP') {
  576. schedule = item.schedule;
  577. schedule.sleep.prev_input = item.prev_input;
  578. schedule.sleep.valid = item.valid;
  579. }
  580. })
  581. if (user.isLogin) {
  582. dispatch(updateScenario(list[0].current_record))
  583. dispatch(setConfigs(list[0].time_input_schema));
  584. dispatch(setScenario(list[0].scenario));
  585. global.scenario = list[0].scenario.name;
  586. }
  587. dispatch(setCurrentRecord(list[0].current_record))
  588. dispatch(setSchedule(schedule))
  589. // setLoaded(true)
  590. }
  591. function getHistory() {
  592. if (user.isLogin)
  593. getClockRecords({
  594. page: 1,
  595. limit: 1,
  596. // part_completed: true
  597. completed: true
  598. }).then(res => {
  599. setRecords((res as any).data)
  600. })
  601. }
  602. global.indexPageRefresh = () => {
  603. getCheckData()
  604. if (global.swiperDayNightRefresh) {
  605. global.swiperDayNightRefresh()
  606. }
  607. }
  608. global.showIndexModal = (isShow: boolean, detail: any, debugNode?: any) => {
  609. global.showModal = isShow
  610. setDebugInfo(debugNode)
  611. setShowModal(isShow)
  612. setModalDetail(detail)
  613. }
  614. global.showIndexModal2 = (isShow: boolean, detail: any) => {
  615. setDebugInfo(null)
  616. global.showModal = isShow
  617. setShowModal2(isShow)
  618. setModalDetail2(detail)
  619. }
  620. global.changeTargetDuration = (duration: number, isFast: boolean) => {
  621. var obj = JSON.parse(JSON.stringify(homeData))
  622. var record = obj.current_record
  623. if (isFast) {
  624. record.fast.target_end_time = record.fast.target_start_time + duration * 60 * 1000
  625. }
  626. else {
  627. record.sleep.target_end_time = record.sleep.target_start_time + duration * 60 * 1000
  628. }
  629. setHomeData(obj)
  630. }
  631. global.updateFastSleepData = (data: any, schedule?: any) => {
  632. if (data.id == (homeData as any).current_record.id) {
  633. var obj = JSON.parse(JSON.stringify(homeData))
  634. obj.current_record = data
  635. if (schedule) {
  636. obj.scenario.schedule = schedule
  637. }
  638. setHomeData(obj)
  639. }
  640. switch (data.scenario) {
  641. case 'FAST':
  642. if (data.status == 'WAIT_FOR_START') {
  643. dispatch(changeFastDuration(data.fast.target_end_time - data.fast.target_start_time))
  644. }
  645. break;
  646. case 'SLEEP':
  647. if (data.status == 'WAIT_FOR_START') {
  648. dispatch(changeSleepDuration(data.sleep.target_end_time - data.sleep.target_start_time))
  649. }
  650. break;
  651. case 'FAST_SLEEP':
  652. if (data.status == 'WAIT_FOR_START') {
  653. dispatch(changeFastDuration(data.fast.target_end_time - data.fast.target_start_time))
  654. }
  655. else if (data.status == 'ONGOING1') {
  656. dispatch(changeSleepDuration(data.sleep.target_end_time - data.sleep.target_start_time))
  657. }
  658. break;
  659. }
  660. }
  661. global.popScheduleAlert = (scenario, startTime) => {
  662. if (process.env.TARO_ENV == 'weapp') {
  663. if (permission.wxPubFollow) {
  664. showAlert({
  665. title: t('feature.track_time_duration.reminders.schedule_title'),
  666. content: scenario.name == 'FAST' ?
  667. t('feature.track_time_duration.reminders.enable_schedule_fast_content', { time: startTime }) :
  668. t('feature.track_time_duration.reminders.enable_schedule_sleep_content', { time: startTime }),
  669. showCancel: false,
  670. confirmText: t('feature.track_time_duration.reminders.ok')
  671. })
  672. }
  673. else {
  674. showAlert({
  675. title: t('feature.track_time_duration.reminders.schedule_title'),
  676. content: scenario.name == 'FAST' ?
  677. t('feature.track_time_duration.reminders.schedule_fast_content', { time: startTime }) :
  678. t('feature.track_time_duration.reminders.schedule_sleep_content', { time: startTime }),
  679. cancelText: t('feature.track_time_duration.reminders.later'),
  680. confirmText: t('feature.track_time_duration.reminders.open'),
  681. showCancel: true,
  682. confirm: () => {
  683. followWxPub()
  684. }
  685. })
  686. }
  687. }
  688. else {
  689. JPush.isNotificationEnabled((res) => {
  690. if (res) {
  691. showAlert({
  692. title: t('feature.track_time_duration.reminders.schedule_title'),
  693. content: scenario.name == 'FAST' ?
  694. t('feature.track_time_duration.reminders.enable_schedule_fast_content', { time: startTime }) :
  695. t('feature.track_time_duration.reminders.enable_schedule_sleep_content', { time: startTime }),
  696. showCancel: false,
  697. confirmText: t('feature.track_time_duration.reminders.ok')
  698. })
  699. }
  700. else {
  701. showAlert({
  702. title: t('feature.track_time_duration.reminders.schedule_title'),
  703. content: scenario.name == 'FAST' ?
  704. t('feature.track_time_duration.reminders.schedule_fast_content', { time: startTime }) :
  705. t('feature.track_time_duration.reminders.schedule_sleep_content', { time: startTime }),
  706. cancelText: t('feature.track_time_duration.reminders.later'),
  707. confirmText: t('feature.track_time_duration.reminders.open'),
  708. showCancel: true,
  709. confirm: () => {
  710. checkNotification()
  711. // Linking.openURL('app-settings:notifications')
  712. }
  713. })
  714. }
  715. })
  716. }
  717. }
  718. global.popMixScheduleAlert = (time1, time2) => {
  719. if (process.env.TARO_ENV == 'weapp') {
  720. if (permission.wxPubFollow) {
  721. showAlert({
  722. title: t('feature.track_time_duration.reminders.schedule_title'),
  723. content: t('feature.track_time_duration.reminders.enable_schedule_mix_content', { time1: time1, time2: time2 }),
  724. showCancel: false,
  725. confirmText: t('feature.track_time_duration.reminders.ok')
  726. })
  727. }
  728. else {
  729. showAlert({
  730. title: t('feature.track_time_duration.reminders.schedule_title'),
  731. content:
  732. t('feature.track_time_duration.reminders.schedule_mix_content'),
  733. cancelText: t('feature.track_time_duration.reminders.later'),
  734. confirmText: t('feature.track_time_duration.reminders.open'),
  735. showCancel: true,
  736. confirm: () => {
  737. followWxPub()
  738. }
  739. })
  740. }
  741. }
  742. else {
  743. JPush.isNotificationEnabled((res) => {
  744. if (res) {
  745. showAlert({
  746. title: t('feature.track_time_duration.reminders.schedule_title'),
  747. content: t('feature.track_time_duration.reminders.enable_schedule_mix_content', { time1: time1, time2: time2 }),
  748. showCancel: false,
  749. confirmText: t('feature.track_time_duration.reminders.ok')
  750. })
  751. }
  752. else {
  753. showAlert({
  754. title: t('feature.track_time_duration.reminders.schedule_title'),
  755. content:
  756. t('feature.track_time_duration.reminders.schedule_mix_content'),
  757. cancelText: t('feature.track_time_duration.reminders.later'),
  758. confirmText: t('feature.track_time_duration.reminders.open'),
  759. showCancel: true,
  760. confirm: () => {
  761. checkNotification()
  762. // Linking.openURL('app-settings:notifications')
  763. }
  764. })
  765. }
  766. })
  767. }
  768. }
  769. function followWxPub() {
  770. const resource = common.resources.filter((item: any) => {
  771. return item.code == 'follow_wx_pub'
  772. })
  773. jumpPage('/pages/common/H5?title=fast16cc 关注服务号&url=' + resource[0].url)
  774. }
  775. function modalContent() {
  776. if (showModal || showModal2) {
  777. return <Modal
  778. testInfo={debugInfo}
  779. dismiss={() => {
  780. setDebugInfo(null)
  781. setShowModal(false);
  782. setShowModal2(false);
  783. global.pauseIndexTimer = false
  784. }}
  785. confirm={() => { }}>
  786. {
  787. showModal ? modalDetail : modalDetail2
  788. }
  789. </Modal>
  790. }
  791. return <View />
  792. }
  793. async function getStorage(key: string) {
  794. try {
  795. const res = await Taro.getStorage({ key });
  796. return res.data;
  797. } catch {
  798. return '';
  799. }
  800. }
  801. function more() {
  802. jumpPage('/pages/common/RecordsHistory?type=time&title=time', 'RecordsHistory', navigation, {
  803. type: 'time',
  804. title: 'time'
  805. })
  806. }
  807. function tapLogin() {
  808. if (!user.isLogin) {
  809. jumpPage('/pages/account/ChooseAuth', 'ChooseAuth', navigation)
  810. }
  811. }
  812. function headerView() {
  813. return <ClockHeader homeData={homeData} />
  814. }
  815. global.scrollToLatest = () => {
  816. needScroll = true;
  817. }
  818. var timestamp = new Date().getTime()
  819. function render() {
  820. if (!loaded) {
  821. return <Layout type={TemplateType.customHeader} header={headerView()} title={t('page.clock.title')} titleShowStyle={NaviBarTitleShowType.scrollToShow}>
  822. <View style={{ width: rpxToPx(750), height: rpxToPx(900), display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center' }}>
  823. <AtActivityIndicator size={40} color="#fff" />
  824. {
  825. process.env.TARO_ENV == 'weapp' && <Tabbar index={0} />
  826. }
  827. </View>
  828. </Layout>
  829. }
  830. return <Layout type={TemplateType.customHeader} header={headerView()} title={t('page.clock.title')} titleShowStyle={NaviBarTitleShowType.scrollToShow}>
  831. <View className="index_container">
  832. {
  833. needShowAddTip && showTip && <Tooltip title="添加到我的小程序" closeTip={() => { setNeedShowAddTip(false) }} />
  834. }
  835. <Text className="count">{count}</Text>
  836. <Box>
  837. <View>
  838. <IndexItem type="FAST_SLEEP" data={homeData} time={timestamp} showStage={false} />
  839. {
  840. user.isLogin ? <IndexConsole record={homeData} count={count} /> : <StageSelector />
  841. }
  842. </View>
  843. </Box>
  844. {
  845. process.env.TARO_ENV == 'weapp' && <DayNightCard isNight={true} count={count} />
  846. }
  847. {
  848. process.env.TARO_ENV == 'rn' && <DayNightSwiper count={count} />
  849. }
  850. {
  851. process.env.TARO_ENV == 'rn' && <View style={{ height: rpxToPx(20) }} />
  852. }
  853. {user.isLogin && <AllRings data={homeData} time={timestamp} />}
  854. {
  855. user.isLogin && records.length > 0 && <View style={{ display: 'flex', flexDirection: 'row', justifyContent: 'space-between', marginTop: rpxToPx(40), }}>
  856. {
  857. <Text className="discovery1" style={{ marginBottom: 0 }}>{t('feature.track_time_duration.record_fast_sleep.header.latest_record')}</Text>
  858. }
  859. {
  860. 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>
  861. }
  862. {
  863. process.env.TARO_ENV == 'rn' && <View onClick={more}>
  864. <GradientText style={{ fontSize: rpxToPx(32), fontWeight: 'bold', marginRight: rpxToPx(46) }}>{t('feature.track_time_duration.record_fast_sleep.header.btn_show_all')}</GradientText>
  865. </View>
  866. }
  867. </View>
  868. }
  869. {
  870. user.isLogin && records.length > 0 && <View id="latest" className="fast_sleep_item_bg">
  871. <RecordFastSleep data={records[0]} type='record' index={-20000} />
  872. </View>
  873. }
  874. {
  875. loaded && !user.isLogin && <View style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', marginTop: rpxToPx(36) }}>
  876. <ChooseScenarioBtn title={t('feature.auth.login.login_now')} background={ColorType.fast} onClick={tapLogin} />
  877. </View>
  878. }
  879. {
  880. user.isLogin && !showErrorPage && <View style={{ marginTop: rpxToPx(60), display: 'flex', flexDirection: 'column' }}>
  881. <Text className="discovery1" >{t('feature.track_time_duration.weekly.title')}</Text>
  882. <WeekCalendar />
  883. </View>
  884. }
  885. {
  886. user.isLogin && <Streaks count={count} />
  887. }
  888. {
  889. user.isLogin && user.test_user && homeData && (homeData as any).access && <View style={{ display: 'flex', flexDirection: 'column' }}>
  890. <Text style={{ color: '#fff', fontSize: 15 }}>current status:{(homeData as any).access.current.qualification.status}</Text>
  891. <Text style={{ color: '#fff', fontSize: 15 }}>previous status:{(homeData as any).access.previous.qualification.status}</Text>
  892. <Text style={{ color: '#fff', fontSize: 15 }}>trigger event:{(homeData as any).access.current.qualification.trigger_event}</Text>
  893. <Text style={{ color: '#fff', fontSize: 15 }}>lost_access_total:{(homeData as any).access.current.qualification.condition.lost_access_total}</Text>
  894. <Text style={{ color: '#fff', fontSize: 15 }}>streak_fast_min_required:{(homeData as any).access.current.qualification.condition.streak_fast_min_required}</Text>
  895. </View>
  896. }
  897. {
  898. process.env.TARO_ENV == 'weapp' && <View style={{ height: 100 }} />
  899. }
  900. {
  901. modalContent()
  902. }
  903. {
  904. homeData && <SegmentPop data={homeData} />
  905. }
  906. {
  907. homeData && <DurationPicker record={(homeData as any).current_record} />
  908. }
  909. <Tabbar index={0} />
  910. </View>
  911. </Layout>
  912. }
  913. // if (process.env.TARO_ENV == 'rn') {
  914. // return <ScrollView>
  915. // {
  916. // render()
  917. // }
  918. // </ScrollView>
  919. // }
  920. return render()
  921. }