Clock.tsx 41 KB

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